Skip to content

Commit

Permalink
Code Formatting
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelahern committed Mar 9, 2024
1 parent 1e4b49c commit 8275356
Show file tree
Hide file tree
Showing 3 changed files with 337 additions and 336 deletions.
146 changes: 73 additions & 73 deletions src/platform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,85 +8,85 @@ import { WattBoxDeviceApi } from "./wattbox";
type WattBoxHomebridgePlatformConfig = PlatformConfig & WattBoxConfig;

export class WattBoxPlatform implements DynamicPlatformPlugin {
public readonly accessories: PlatformAccessory[] = [];
public readonly config: WattBoxHomebridgePlatformConfig;
public readonly accessories: PlatformAccessory[] = [];
public readonly config: WattBoxHomebridgePlatformConfig;

constructor(public readonly log: Logger, public readonly platformConfig: PlatformConfig, public readonly api: API) {
this.config = <WattBoxHomebridgePlatformConfig>this.platformConfig;
constructor(public readonly log: Logger, public readonly platformConfig: PlatformConfig, public readonly api: API) {
this.config = <WattBoxHomebridgePlatformConfig>this.platformConfig;

this.api.on('didFinishLaunching', async () => {
this.discoverDevices();
});
}

public configureAccessory(accessory: PlatformAccessory) {
this.log.info(`[${accessory.displayName}] Loading accessory from cache...`);
this.accessories.push(accessory);
}

private async discoverDevices() {
const uuids: Set<string> = new Set();
for (const deviceConfig of this.config.devices) {
const uuid = this.api.hap.uuid.generate(deviceConfig.serviceTag);
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
const accessory = existingAccessory ?? new this.api.platformAccessory(deviceConfig.name, uuid);

const deviceApi = new WattBoxDeviceApi(deviceConfig.host, deviceConfig.username, deviceConfig.password, this.log, this.config.debug ?? false, `[${accessory.displayName}]`);
this.api.on('didFinishLaunching', async () => {
this.discoverDevices();
});
}

try {
const deviceInfo = await deviceApi.getDeviceInfo();
public configureAccessory(accessory: PlatformAccessory) {
this.log.info(`[${accessory.displayName}] Loading accessory from cache...`);
this.accessories.push(accessory);
}

if (deviceConfig.serviceTag != deviceInfo.serviceTag) {
this.log.warn(`[${accessory.displayName}] Service tag mismatch detected!`);
private async discoverDevices() {
const uuids: Set<string> = new Set();
for (const deviceConfig of this.config.devices) {
const uuid = this.api.hap.uuid.generate(deviceConfig.serviceTag);
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
const accessory = existingAccessory ?? new this.api.platformAccessory(deviceConfig.name, uuid);

const deviceApi = new WattBoxDeviceApi(deviceConfig.host, deviceConfig.username, deviceConfig.password, this.log, this.config.debug ?? false, `[${accessory.displayName}]`);

try {
const deviceInfo = await deviceApi.getDeviceInfo();

if (deviceConfig.serviceTag != deviceInfo.serviceTag) {
this.log.warn(`[${accessory.displayName}] Service tag mismatch detected!`);
}

accessory.context = <WattBoxPlatformAccessoryContext>{
deviceConfig: deviceConfig,
deviceInfo: deviceInfo
};
}
catch (error: unknown) {
this.log.error(`[${accessory.displayName}] ${(<Error>error).message}`);

if (existingAccessory) {
this.log.error(`[${accessory.displayName}] Using cache to initialize accessory, check configuration!`);
}
else {
this.log.error(`[${accessory.displayName}] Cannot initialize new device/accessory, check configuration!`);
continue;
}
}

(accessory.getService(this.api.hap.Service.AccessoryInformation) || accessory.addService(this.api.hap.Service.AccessoryInformation))
.setCharacteristic(this.api.hap.Characteristic.Name, deviceConfig.name)
.setCharacteristic(this.api.hap.Characteristic.Manufacturer, 'WattBox')
.setCharacteristic(this.api.hap.Characteristic.Model, (<WattBoxPlatformAccessoryContext>accessory.context).deviceInfo.model)
.setCharacteristic(this.api.hap.Characteristic.SerialNumber, (<WattBoxPlatformAccessoryContext>accessory.context).deviceInfo.serviceTag)
.setCharacteristic(this.api.hap.Characteristic.FirmwareRevision, (<WattBoxPlatformAccessoryContext>accessory.context).deviceInfo.firmware);

if ((<WattBoxPlatformAccessoryContext>accessory.context).deviceInfo.upsConnection) {
accessory.getService(this.api.hap.Service.Battery) || accessory.addService(this.api.hap.Service.Battery, "UPS Battery Backup");
}

for (let i = 0; i < (<WattBoxPlatformAccessoryContext>accessory.context).deviceInfo.outletNames.length; i++) {
this.log.info(`[${accessory.displayName}] [${(i + 1).toString().padStart(2)}] Creating outlet with name "${(<WattBoxPlatformAccessoryContext>accessory.context).deviceInfo.outletNames[i]}"`);
new WattBoxPlatformAccessory(this, accessory, deviceApi, i + 1, (<WattBoxPlatformAccessoryContext>accessory.context).deviceInfo.outletNames[i]);
}

if (existingAccessory) {
this.api.updatePlatformAccessories([accessory]);
uuids.add(uuid);
}
else {
this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory]);
uuids.add(uuid);
}
}

accessory.context = <WattBoxPlatformAccessoryContext>{
deviceConfig: deviceConfig,
deviceInfo: deviceInfo
};
}
catch (error: unknown) {
this.log.error(`[${accessory.displayName}] ${(<Error>error).message}`);

if (existingAccessory) {
this.log.error(`[${accessory.displayName}] Using cache to initialize accessory, check configuration!`);
}
else {
this.log.error(`[${accessory.displayName}] Cannot initialize new device/accessory, check configuration!`);
continue;
const orphanedAccessories = this.accessories.filter(accessory => !uuids.has(accessory.UUID));
for (const orphanedAccessory of orphanedAccessories) {
this.log.info(`[${orphanedAccessory.displayName}] Removing orphaned accessory from cache...`);
this.api.unregisterPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [orphanedAccessory]);
}
}

(accessory.getService(this.api.hap.Service.AccessoryInformation) || accessory.addService(this.api.hap.Service.AccessoryInformation))
.setCharacteristic(this.api.hap.Characteristic.Name, deviceConfig.name)
.setCharacteristic(this.api.hap.Characteristic.Manufacturer, 'WattBox')
.setCharacteristic(this.api.hap.Characteristic.Model, (<WattBoxPlatformAccessoryContext>accessory.context).deviceInfo.model)
.setCharacteristic(this.api.hap.Characteristic.SerialNumber, (<WattBoxPlatformAccessoryContext>accessory.context).deviceInfo.serviceTag)
.setCharacteristic(this.api.hap.Characteristic.FirmwareRevision, (<WattBoxPlatformAccessoryContext>accessory.context).deviceInfo.firmware);

if ((<WattBoxPlatformAccessoryContext>accessory.context).deviceInfo.upsConnection) {
accessory.getService(this.api.hap.Service.Battery) || accessory.addService(this.api.hap.Service.Battery, "UPS Battery Backup");
}

for (let i = 0; i < (<WattBoxPlatformAccessoryContext>accessory.context).deviceInfo.outletNames.length; i++) {
this.log.info(`[${accessory.displayName}] [${(i + 1).toString().padStart(2)}] Creating outlet with name "${(<WattBoxPlatformAccessoryContext>accessory.context).deviceInfo.outletNames[i]}"`);
new WattBoxPlatformAccessory(this, accessory, deviceApi, i + 1, (<WattBoxPlatformAccessoryContext>accessory.context).deviceInfo.outletNames[i]);
}

if (existingAccessory) {
this.api.updatePlatformAccessories([accessory]);
uuids.add(uuid);
}
else {
this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory]);
uuids.add(uuid);
}
}

const orphanedAccessories = this.accessories.filter(accessory => !uuids.has(accessory.UUID));
for (const orphanedAccessory of orphanedAccessories) {
this.log.info(`[${orphanedAccessory.displayName}] Removing orphaned accessory from cache...`);
this.api.unregisterPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [orphanedAccessory]);
}
}
}
126 changes: 63 additions & 63 deletions src/platformAccessory.ts
Original file line number Diff line number Diff line change
@@ -1,82 +1,82 @@
import { CharacteristicValue, Logger, PlatformAccessory } from "homebridge";

import { WattBoxDeviceConfig } from "./config";
import { WattBoxPlatform } from "./platform";
import { WattBoxDeviceApi, WattBoxDeviceInfo, WattBoxOutletAction, WattBoxOutletStatus } from "./wattbox";
import { WattBoxDeviceConfig } from "./config";

export class WattBoxPlatformAccessory {
private readonly context: WattBoxPlatformAccessoryContext;
private readonly log: Logger;
private readonly logPrefix: string;

private outletStatus = WattBoxOutletStatus.UNKNOWN;

constructor(private readonly platform: WattBoxPlatform, private readonly accessory: PlatformAccessory, private readonly deviceApi: WattBoxDeviceApi, private readonly outletId: number, private readonly outletName: string) {
this.context = <WattBoxPlatformAccessoryContext>this.accessory.context;
this.log = this.platform.log;
this.logPrefix = `[${this.accessory.displayName}] [${this.outletId.toString().padStart(2)}]`;

const outletServiceId = `${this.context.deviceInfo.serviceTag}:${this.outletId}`;
const outletService = (this.accessory.getServiceById(this.platform.api.hap.Service.Outlet, outletServiceId) || this.accessory.addService(this.platform.api.hap.Service.Outlet, `${this.outletId}: ${this.outletName}`, outletServiceId))
.setCharacteristic(this.platform.api.hap.Characteristic.Name, `${this.outletId} ${this.outletName}`);

const outletServiceOnCharacteristic = outletService.getCharacteristic(this.platform.api.hap.Characteristic.On)
.onGet(this.getOn.bind(this))
.onSet(this.setOn.bind(this));

const batteryService = this.accessory.getService(this.platform.api.hap.Service.Battery);
private readonly context: WattBoxPlatformAccessoryContext;
private readonly log: Logger;
private readonly logPrefix: string;

private outletStatus = WattBoxOutletStatus.UNKNOWN;

constructor(private readonly platform: WattBoxPlatform, private readonly accessory: PlatformAccessory, private readonly deviceApi: WattBoxDeviceApi, private readonly outletId: number, private readonly outletName: string) {
this.context = <WattBoxPlatformAccessoryContext>this.accessory.context;
this.log = this.platform.log;
this.logPrefix = `[${this.accessory.displayName}] [${this.outletId.toString().padStart(2)}]`;

const outletServiceId = `${this.context.deviceInfo.serviceTag}:${this.outletId}`;
const outletService = (this.accessory.getServiceById(this.platform.api.hap.Service.Outlet, outletServiceId) || this.accessory.addService(this.platform.api.hap.Service.Outlet, `${this.outletId}: ${this.outletName}`, outletServiceId))
.setCharacteristic(this.platform.api.hap.Characteristic.Name, `${this.outletId} ${this.outletName}`);

const outletServiceOnCharacteristic = outletService.getCharacteristic(this.platform.api.hap.Characteristic.On)
.onGet(this.getOn.bind(this))
.onSet(this.setOn.bind(this));

const batteryService = this.accessory.getService(this.platform.api.hap.Service.Battery);

this.deviceApi.subscribeDeviceStatus(
this.context.deviceInfo.serviceTag,
(deviceStatus) => {
this.log.debug(`${this.logPrefix} status -> ${WattBoxOutletStatus[this.outletStatus]}:${WattBoxOutletStatus[deviceStatus.outletStatus[this.outletId - 1]]}`);

if (this.outletStatus !== deviceStatus.outletStatus[this.outletId - 1]) {
this.outletStatus = deviceStatus.outletStatus[this.outletId - 1];
outletServiceOnCharacteristic.updateValue(!!deviceStatus.outletStatus[this.outletId - 1]);
}

if (batteryService && deviceStatus.batteryLevel !== undefined && deviceStatus.powerLost !== undefined) {
batteryService
.updateCharacteristic(this.platform.api.hap.Characteristic.BatteryLevel, deviceStatus.batteryLevel)
.updateCharacteristic(this.platform.api.hap.Characteristic.ChargingState, deviceStatus.powerLost ? this.platform.api.hap.Characteristic.ChargingState.NOT_CHARGING : this.platform.api.hap.Characteristic.ChargingState.CHARGING)
.updateCharacteristic(this.platform.api.hap.Characteristic.StatusLowBattery, deviceStatus.powerLost ? this.platform.api.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW : this.platform.api.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL);
}
}
);
}

this.deviceApi.subscribeDeviceStatus(
this.context.deviceInfo.serviceTag,
(deviceStatus) => {
this.log.debug(`${this.logPrefix} status -> ${WattBoxOutletStatus[this.outletStatus]}:${WattBoxOutletStatus[deviceStatus.outletStatus[this.outletId - 1]]}`);
private getOn(): CharacteristicValue {
this.log.debug(`${this.logPrefix} getOn -> ${WattBoxOutletStatus[this.outletStatus]}`)

if (this.outletStatus !== deviceStatus.outletStatus[this.outletId - 1]) {
this.outletStatus = deviceStatus.outletStatus[this.outletId - 1];
outletServiceOnCharacteristic.updateValue(!!deviceStatus.outletStatus[this.outletId - 1]);
if (this.outletStatus === WattBoxOutletStatus.UNKNOWN) {
throw new this.platform.api.hap.HapStatusError(this.platform.api.hap.HAPStatus.NOT_ALLOWED_IN_CURRENT_STATE);
}

if (batteryService && deviceStatus.batteryLevel !== undefined && deviceStatus.powerLost !== undefined) {
batteryService
.updateCharacteristic(this.platform.api.hap.Characteristic.BatteryLevel, deviceStatus.batteryLevel)
.updateCharacteristic(this.platform.api.hap.Characteristic.ChargingState, deviceStatus.powerLost ? this.platform.api.hap.Characteristic.ChargingState.NOT_CHARGING : this.platform.api.hap.Characteristic.ChargingState.CHARGING)
.updateCharacteristic(this.platform.api.hap.Characteristic.StatusLowBattery, deviceStatus.powerLost ? this.platform.api.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW : this.platform.api.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL);
}
}
);
}

private getOn(): CharacteristicValue {
this.log.debug(`${this.logPrefix} getOn -> ${WattBoxOutletStatus[this.outletStatus]}`)

if (this.outletStatus === WattBoxOutletStatus.UNKNOWN) {
throw new this.platform.api.hap.HapStatusError(this.platform.api.hap.HAPStatus.NOT_ALLOWED_IN_CURRENT_STATE);
return this.outletStatus === WattBoxOutletStatus.ON;
}

return this.outletStatus === WattBoxOutletStatus.ON;
}

private async setOn(value: CharacteristicValue) {
if (this.context.deviceConfig.outletsReadOnly) {
this.log.debug(`${this.logPrefix} setOn(NOOP)`)
throw new this.platform.api.hap.HapStatusError(this.platform.api.hap.HAPStatus.READ_ONLY_CHARACTERISTIC);
}
private async setOn(value: CharacteristicValue) {
if (this.context.deviceConfig.outletsReadOnly) {
this.log.debug(`${this.logPrefix} setOn(NOOP)`)
throw new this.platform.api.hap.HapStatusError(this.platform.api.hap.HAPStatus.READ_ONLY_CHARACTERISTIC);
}

const action = this.context.deviceConfig.outletsResetOnly ? WattBoxOutletAction.RESET : (value ? WattBoxOutletAction.ON : WattBoxOutletAction.OFF);
this.log.debug(`${this.logPrefix} setOn(${WattBoxOutletAction[action]})`)
const action = this.context.deviceConfig.outletsResetOnly ? WattBoxOutletAction.RESET : (value ? WattBoxOutletAction.ON : WattBoxOutletAction.OFF);
this.log.debug(`${this.logPrefix} setOn(${WattBoxOutletAction[action]})`)

try {
await this.deviceApi.setOutletAction(this.outletId, action);
this.outletStatus = value ? WattBoxOutletStatus.ON : WattBoxOutletStatus.OFF;
}
catch (error: unknown) {
this.log.error(`${this.logPrefix} setOn(${WattBoxOutletAction[action]}) -> ${(<Error>error).message}`)
throw new this.platform.api.hap.HapStatusError(this.platform.api.hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE);
try {
await this.deviceApi.setOutletAction(this.outletId, action);
this.outletStatus = value ? WattBoxOutletStatus.ON : WattBoxOutletStatus.OFF;
}
catch (error: unknown) {
this.log.error(`${this.logPrefix} setOn(${WattBoxOutletAction[action]}) -> ${(<Error>error).message}`)
throw new this.platform.api.hap.HapStatusError(this.platform.api.hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE);
}
}
}
}

export interface WattBoxPlatformAccessoryContext {
deviceConfig: WattBoxDeviceConfig
deviceInfo: WattBoxDeviceInfo;
deviceConfig: WattBoxDeviceConfig
deviceInfo: WattBoxDeviceInfo;
}
Loading

0 comments on commit 8275356

Please sign in to comment.