matterbridge-daikin-ac
Version:
Daikin AC Matterbridge plugin
210 lines (188 loc) • 8.81 kB
text/typescript
import { BasicInfoResponse, ControlInfo, DaikinAC, SensorInfoResponse } from 'daikin-controller';
import { DaikinAcPlatform } from './platform.js';
import { DaikinAcMode } from './models/DaikinAcMode.js';
import { DaikinAcState } from './models/DaikinAcState.js';
class DaikinAcDevice {
private ip: string;
private connectionPromise: Promise<void>;
private platform: DaikinAcPlatform;
private daikinDevice!: DaikinAC;
private isConnected: boolean = false;
public currentState: DaikinAcState | undefined = undefined;
public name: string = '';
private powerUpdatedCallback: ((power: boolean) => void) | undefined;
private indoorTempUpdatedCallback: ((indorrTemp: number) => void) | undefined;
private targetTempUpdatedCallback: ((targetTemp: number) => void) | undefined;
private modeUpdatedCallback: ((power: boolean, mode: number) => void) | undefined;
constructor(platform: DaikinAcPlatform, ip: string, options: { useGetToPost?: boolean } = {}) {
this.ip = ip;
this.platform = platform;
// Create the connection promise
this.connectionPromise = new Promise<void>((resolve, reject) => {
this.daikinDevice = new DaikinAC(this.ip, options, (err: Error | null) => {
if (err) {
reject(err);
} else {
this.isConnected = true;
resolve();
}
});
});
}
public async connect() {
try {
this.platform.log.info(`Connecting to Daikin AC at ${this.ip}`);
await this.connectionPromise;
this.platform.log.info(`Connected`);
} catch (error) {
this.platform.log.error(`Failed to connect to Daikin AC:`, error);
throw error;
}
const info = await this.getCommonBasicInfoAsync();
this.name = info.name ?? `Daikin AC ${this.ip}`;
await this.getACControlInfo();
await this.getACControlInfo();
this.updateCurrentState();
}
public startUpdates(
powerUpdatedCallback: (power: boolean) => void,
modeUpdatedCallback: (power: boolean, mode: number) => void,
indoorTempUpdatedCallback: (indoorTemp: number) => void,
targetTempUpdatedCallback: (targetTemp: number) => void,
) {
this.powerUpdatedCallback = powerUpdatedCallback;
this.modeUpdatedCallback = modeUpdatedCallback;
this.indoorTempUpdatedCallback = indoorTempUpdatedCallback;
this.targetTempUpdatedCallback = targetTempUpdatedCallback;
this.daikinDevice.setUpdate(15000, this.calculateDelta.bind(this));
}
private calculateDelta() {
if (this.currentState?.power !== this.daikinDevice.currentACControlInfo?.power) {
this.platform.log.info(`Power changed from ${this.currentState?.power} to ${this.daikinDevice.currentACControlInfo?.power}`);
if (this.powerUpdatedCallback && this.daikinDevice.currentACControlInfo?.power !== undefined) {
this.powerUpdatedCallback(this.daikinDevice.currentACControlInfo.power);
}
}
if (this.currentState?.mode !== this.daikinDevice.currentACControlInfo?.mode) {
this.platform.log.info(`Mode changed from ${this.currentState?.mode} to ${this.daikinDevice.currentACControlInfo?.mode}`);
if (this.modeUpdatedCallback && this.daikinDevice.currentACControlInfo?.power !== undefined && this.daikinDevice.currentACControlInfo?.mode !== undefined) {
this.modeUpdatedCallback(this.daikinDevice.currentACControlInfo.power, this.daikinDevice.currentACControlInfo.mode);
}
}
if (this.currentState?.indoorTemperature !== this.daikinDevice.currentACSensorInfo?.indoorTemperature) {
this.platform.log.info(`Indoor temperature changed from ${this.currentState?.indoorTemperature} to ${this.daikinDevice.currentACSensorInfo?.indoorTemperature}`);
if (this.indoorTempUpdatedCallback && this.daikinDevice.currentACSensorInfo?.indoorTemperature !== undefined) {
this.indoorTempUpdatedCallback(this.daikinDevice.currentACSensorInfo.indoorTemperature);
}
}
if (this.currentState?.targetTemperature !== this.daikinDevice.currentACControlInfo?.targetTemperature) {
this.platform.log.info(`Target temperature changed from ${this.currentState?.targetTemperature} to ${this.daikinDevice.currentACControlInfo?.targetTemperature}`);
if (
this.targetTempUpdatedCallback &&
this.daikinDevice.currentACControlInfo?.targetTemperature !== undefined &&
this.daikinDevice.currentACControlInfo?.targetTemperature !== 'M'
) {
this.targetTempUpdatedCallback(this.daikinDevice.currentACControlInfo.targetTemperature);
}
}
this.updateCurrentState();
}
private updateCurrentState() {
if (!this.currentState) {
this.currentState = new DaikinAcState();
}
this.currentState.indoorTemperature = this.daikinDevice.currentACSensorInfo?.indoorTemperature;
this.currentState.targetTemperature = this.daikinDevice.currentACControlInfo?.targetTemperature;
this.currentState.power = this.daikinDevice.currentACControlInfo?.power;
this.currentState.mode = this.daikinDevice.currentACControlInfo?.mode;
}
public async getCommonBasicInfoAsync(): Promise<BasicInfoResponse> {
if (!this.isConnected) {
this.platform.log.warn(`Connect needs to be called first`);
await this.connect();
}
return new Promise((resolve, reject) => {
this.daikinDevice.getCommonBasicInfo((err: Error | null, data: BasicInfoResponse | null) => {
if (err) {
reject(err);
} else {
if (data === null) {
reject(new Error('No data received from Daikin AC'));
return;
}
resolve(data);
}
});
});
}
public async getACControlInfo(): Promise<ControlInfo> {
if (!this.isConnected) {
this.platform.log.warn(`Connect needs to be called first`);
await this.connect();
}
return new Promise((resolve, reject) => {
this.daikinDevice.getACControlInfo((err: Error | null, data: ControlInfo | null) => {
if (err) {
reject(err);
} else {
if (data === null) {
reject(new Error('No data received from Daikin AC'));
return;
}
resolve(data);
}
});
});
}
public async setACControlInfo(obj: Partial<ControlInfo>): Promise<ControlInfo> {
if (!this.isConnected) {
this.platform.log.warn(`Connect needs to be called first`);
await this.connect();
}
return new Promise((resolve, reject) => {
this.daikinDevice.setACControlInfo(obj, (err: Error | null, data: ControlInfo | null) => {
if (err) {
reject(err);
} else {
if (data === null) {
reject(new Error('No data received from Daikin AC'));
return;
}
resolve(data);
}
});
});
}
public async getACSensorInfo(): Promise<SensorInfoResponse> {
if (!this.isConnected) {
this.platform.log.warn(`Connect needs to be called first`);
await this.connect();
}
return new Promise((resolve, reject) => {
this.daikinDevice.getACSensorInfo((err: Error | null, data: SensorInfoResponse | null) => {
if (err) {
reject(err);
} else {
if (data === null) {
reject(new Error('No data received from Daikin AC'));
return;
}
resolve(data);
}
});
});
}
public async setMode(mode: DaikinAcMode) {
await this.setACControlInfo({ mode: mode });
}
public async switchOn() {
await this.setACControlInfo({ power: true });
}
public async switchOff() {
await this.setACControlInfo({ power: false });
}
public async setTargetTemperature(newValue: number) {
await this.setACControlInfo({ targetTemperature: newValue });
}
}
export { DaikinAcDevice };