generated from homebridge/homebridge-plugin-template
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
274 additions
and
47 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import { Logging, PlatformAccessory, Service, WithUUID } from "homebridge"; | ||
import { EnergySpecific, } from "tesla-fleet-api"; | ||
import { TeslaFleetApiPlatform } from "../platform.js"; | ||
import { EventEmitter } from "../utils/event.js"; | ||
import { EnergyAccessory, EnergyContext, EnergyDataEvent } from "../energy.js"; | ||
|
||
export abstract class BaseService { | ||
protected service: Service; | ||
protected log: Logging; | ||
protected platform: TeslaFleetApiPlatform; | ||
protected accessory: PlatformAccessory<EnergyContext>; | ||
protected emitter: EventEmitter<EnergyDataEvent>; | ||
protected energy: EnergySpecific; | ||
|
||
constructor( | ||
protected parent: EnergyAccessory, | ||
definition: WithUUID<typeof Service>, | ||
name: string, | ||
subtype: string, | ||
) { | ||
this.log = parent.platform.log; | ||
this.platform = parent.platform; | ||
this.accessory = parent.accessory; | ||
this.emitter = parent.emitter; | ||
this.energy = parent.energy; | ||
|
||
name = parent.platform.config.prefixName ? `${this.parent.accessory.displayName} ${name}` : name; | ||
|
||
this.service = | ||
this.accessory.getServiceById(definition, subtype) || | ||
this.accessory.addService(definition, name, subtype); | ||
|
||
// Set the configured name if it's not already set since Homekit wont use the display name | ||
const ConfiguredName = this.service.getCharacteristic(this.platform.Characteristic.ConfiguredName); | ||
if (!ConfiguredName.value) { | ||
this.log.debug(`Configured name changing to ${name}`); | ||
ConfiguredName.updateValue(name); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import { EnergyAccessory } from "../energy.js"; | ||
import { BaseService } from "./base.js"; | ||
|
||
export class BatteryService extends BaseService { | ||
constructor(parent: EnergyAccessory) { | ||
super(parent, parent.platform.Service.Battery, "Battery", "battery"); | ||
|
||
const batteryLevel = this.service | ||
.getCharacteristic(this.parent.platform.Characteristic.BatteryLevel); | ||
|
||
const chargingState = this.service | ||
.getCharacteristic(this.parent.platform.Characteristic.ChargingState); | ||
|
||
const lowBattery = this.service | ||
.getCharacteristic(this.parent.platform.Characteristic.StatusLowBattery); | ||
|
||
this.parent.emitter.on("live_status", (data) => { | ||
batteryLevel.updateValue(this.getLevel(data)); | ||
chargingState.updateValue(this.getChargingState(data)); | ||
lowBattery.updateValue(this.getLowBattery(data)); | ||
}); | ||
} | ||
|
||
getLevel(data): number { | ||
return data.charge_state?.battery_level ?? 50; | ||
} | ||
|
||
getChargingState(data): number { | ||
switch (data.charge_state?.charging_state) { | ||
case "Starting": | ||
return this.parent.platform.Characteristic.ChargingState.CHARGING; | ||
case "Charging": | ||
return this.parent.platform.Characteristic.ChargingState.CHARGING; | ||
case "Disconnected": | ||
return this.parent.platform.Characteristic.ChargingState.NOT_CHARGEABLE; | ||
case "NoPower": | ||
return this.parent.platform.Characteristic.ChargingState.NOT_CHARGEABLE; | ||
default: | ||
return this.parent.platform.Characteristic.ChargingState.NOT_CHARGING; | ||
} | ||
} | ||
|
||
getLowBattery(data): boolean { | ||
return this.getLevel(data) <= 20; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { EnergyAccessory } from "../energy.js"; | ||
import { BaseService } from "./base.js"; | ||
|
||
export class ChargeFromGrid extends BaseService { | ||
constructor(parent: EnergyAccessory) { | ||
super(parent, parent.platform.Service.Switch, "Charge From Grid", "chargefromgrid"); | ||
|
||
const on = this.service | ||
.getCharacteristic(this.parent.platform.Characteristic.On) | ||
.onSet(async (value) => { | ||
if (typeof value === "boolean") { | ||
await this.energy.grid_import_export().then(() => on.updateValue(value)); | ||
} | ||
}); | ||
|
||
this.parent.emitter.on("site_info", (data) => { | ||
if (typeof data.components.disallow_charge_from_grid_with_solar_installed === "boolean") { | ||
on.updateValue(data.components.disallow_charge_from_grid_with_solar_installed); | ||
} | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
import { PlatformAccessory } from "homebridge"; | ||
|
||
import { EnergySpecific } from "tesla-fleet-api"; | ||
import { | ||
LiveStatusResponse | ||
} from "tesla-fleet-api/dist/types/live_status"; | ||
import { | ||
SiteInfoResponse | ||
} from "tesla-fleet-api/dist/types/site_info.js"; | ||
import { TeslaFleetApiPlatform } from "./platform.js"; | ||
import { REFRESH_INTERVAL } from "./settings.js"; | ||
import { EventEmitter } from "./utils/event.js"; | ||
import { ChargeFromGrid } from "./energy-services/changefromgrid.js"; | ||
|
||
export type EnergyContext = { | ||
id: number; | ||
battery: boolean; | ||
grid: boolean; | ||
solar: boolean; | ||
}; | ||
|
||
export interface EnergyDataEvent { | ||
live_status(data: LiveStatusResponse): void; | ||
site_info(data: SiteInfoResponse): void; | ||
} | ||
|
||
export class EnergyAccessory { | ||
public energy: EnergySpecific; | ||
public emitter: EventEmitter<EnergyDataEvent>; | ||
|
||
constructor( | ||
public readonly platform: TeslaFleetApiPlatform, | ||
public readonly accessory: PlatformAccessory<EnergyContext> | ||
) { | ||
if (!this.platform.TeslaFleetApi?.energy) { | ||
throw new Error("TeslaFleetApi not initialized"); | ||
} | ||
|
||
this.energy = this.platform.TeslaFleetApi.energy.specific( | ||
this.accessory.context.id | ||
); | ||
|
||
this.emitter = new EventEmitter(); | ||
|
||
// Create services | ||
if (this.accessory.context.battery) { | ||
new ChargeFromGrid(this); | ||
} | ||
|
||
// Get data and schedule refresh | ||
|
||
this.refresh(); | ||
setInterval(() => this.refresh(), REFRESH_INTERVAL); | ||
} | ||
|
||
async refresh(): Promise<void> { | ||
this.energy | ||
.site_info() | ||
.then((data) => { | ||
this.emitter.emit("site_info", data); | ||
}) | ||
.catch(({ status, data }) => { | ||
if (data?.error) { | ||
this.platform.log.warn(`${this.accessory.displayName} site_info return status ${status}: ${data.error}`); | ||
return; | ||
} | ||
this.platform.log.error(`${this.accessory.displayName} site_info return status ${status}: ${data}`); | ||
}); | ||
this.energy | ||
.live_status() | ||
.then((data) => { | ||
this.emitter.emit("live_status", data); | ||
}) | ||
.catch(({ status, data }) => { | ||
if (data?.error) { | ||
this.platform.log.warn(`${this.accessory.displayName} live_status return status ${status}: ${data.error}`); | ||
return; | ||
} | ||
this.platform.log.error(`${this.accessory.displayName} live_status return status ${status}: ${data}`); | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters