Skip to content

Commit

Permalink
Changing battery to identify charging while docked. (#335)
Browse files Browse the repository at this point in the history
  • Loading branch information
jeff-winn authored Jul 4, 2023
1 parent 8497a35 commit 664bcc7
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 5 deletions.
22 changes: 17 additions & 5 deletions src/services/batteryInformation.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { API, Characteristic, PlatformAccessory, Service } from 'homebridge';
import { Battery, MowerState, State } from '../model';
import { Activity, Battery, MowerState, State } from '../model';
import { MowerContext } from '../mowerAccessory';
import { AbstractAccessoryService } from './homebridge/abstractAccessoryService';

Expand All @@ -25,7 +25,10 @@ export interface BatteryInformation {
setChargingState(state: MowerState): void;
}

export class BatteryInformationImpl extends AbstractAccessoryService implements BatteryInformation {
export class BatteryInformationImpl extends AbstractAccessoryService implements BatteryInformation {
private lastBattery?: Battery;
private lastState?: MowerState;

private batteryService?: Service;
private lowBattery?: Characteristic;
private batteryLevel?: Characteristic;
Expand All @@ -50,12 +53,18 @@ export class BatteryInformationImpl extends AbstractAccessoryService implements
this.chargingState = this.batteryService.getCharacteristic(this.Characteristic.ChargingState);
}

public setChargingState(state: MowerState) {
public setChargingState(state: MowerState): void {
this.lastState = state;
this.refreshChargingState();
}

private refreshChargingState(): void {
if (this.chargingState === undefined) {
throw new Error('The service has not been initialized.');
}

if (state.state === State.CHARGING) {
if (this.lastState !== undefined && (this.lastState.state === State.CHARGING ||
(this.lastState.activity === Activity.PARKED && this.lastBattery !== undefined && this.lastBattery.level < 100))) {
this.chargingState.updateValue(this.Characteristic.ChargingState.CHARGING);
} else {
this.chargingState.updateValue(this.Characteristic.ChargingState.NOT_CHARGING);
Expand All @@ -67,12 +76,15 @@ export class BatteryInformationImpl extends AbstractAccessoryService implements
throw new Error('The service has not been initialized.');
}

this.batteryLevel.updateValue(battery.level);
this.batteryLevel.updateValue(battery.level);

if (battery.level <= 20) {
this.lowBattery.updateValue(this.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW);
} else {
this.lowBattery.updateValue(this.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL);
}

this.lastBattery = battery;
this.refreshChargingState();
}
}
62 changes: 62 additions & 0 deletions test/services/batteryInformation.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,68 @@ describe('BatteryServiceImpl', () => {
batteryLevel.verify(o => o.updateValue(100), Times.Once());
});

it('sets the battery service as charging while parked with less than 100 percent battery', () => {
const serviceInstance = new Mock<Service>();
const lowBattery = new Mock<Characteristic>();
const batteryLevel = new Mock<Characteristic>();
const chargingState = new Mock<Characteristic>();

lowBattery.setup(o => o.updateValue(It.IsAny<CharacteristicValue>())).returns(lowBattery.object());
batteryLevel.setup(o => o.updateValue(It.IsAny<CharacteristicValue>())).returns(batteryLevel.object());
chargingState.setup(o => o.updateValue(It.IsAny<CharacteristicValue>())).returns(chargingState.object());

accessory.setup(o => o.getService(Service.Battery)).returns(serviceInstance.object());

serviceInstance.setup(o => o.getCharacteristic(Characteristic.StatusLowBattery)).returns(lowBattery.object());
serviceInstance.setup(o => o.getCharacteristic(Characteristic.BatteryLevel)).returns(batteryLevel.object());
serviceInstance.setup(o => o.getCharacteristic(Characteristic.ChargingState)).returns(chargingState.object());

target.init();

target.setBatteryLevel({
level: 99
});

target.setChargingState({
activity: Activity.PARKED,
state: State.IDLE
});

chargingState.verify(o => o.updateValue(Characteristic.ChargingState.CHARGING), Times.Once());
lowBattery.verify(o => o.updateValue(Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL), Times.Once());
});

it('sets the battery service as not charging while parked with 100 percent battery', () => {
const serviceInstance = new Mock<Service>();
const lowBattery = new Mock<Characteristic>();
const batteryLevel = new Mock<Characteristic>();
const chargingState = new Mock<Characteristic>();

lowBattery.setup(o => o.updateValue(It.IsAny<CharacteristicValue>())).returns(lowBattery.object());
batteryLevel.setup(o => o.updateValue(It.IsAny<CharacteristicValue>())).returns(batteryLevel.object());
chargingState.setup(o => o.updateValue(It.IsAny<CharacteristicValue>())).returns(chargingState.object());

accessory.setup(o => o.getService(Service.Battery)).returns(serviceInstance.object());

serviceInstance.setup(o => o.getCharacteristic(Characteristic.StatusLowBattery)).returns(lowBattery.object());
serviceInstance.setup(o => o.getCharacteristic(Characteristic.BatteryLevel)).returns(batteryLevel.object());
serviceInstance.setup(o => o.getCharacteristic(Characteristic.ChargingState)).returns(chargingState.object());

target.init();

target.setChargingState({
activity: Activity.PARKED,
state: State.IDLE
});

target.setBatteryLevel({
level: 100
});

chargingState.verify(o => o.updateValue(Characteristic.ChargingState.NOT_CHARGING), Times.Exactly(2));
lowBattery.verify(o => o.updateValue(Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL), Times.Once());
});

it('sets the battery service as charging', () => {
const serviceInstance = new Mock<Service>();
const lowBattery = new Mock<Characteristic>();
Expand Down

0 comments on commit 664bcc7

Please sign in to comment.