UNPKG

daikin-controller

Version:

Control Daikin Air Conditioner devices using nodejs

293 lines (257 loc) 12.2 kB
import { DaikinDataParser } from './DaikinDataParser'; import { BasicInfoResponse, ControlInfo, ModelInfoResponse, RemoteMethodResponse, RequestDict, SensorInfoResponse, WeekPowerExtendedResponse, WeekPowerResponse, YearPowerExtendedResponse, YearPowerResponse, } from './models'; import { SetCommandResponse, SetSpecialModeRequest } from './models'; import { SpecialModeKind } from './DaikinACTypes'; import { DemandControl } from './models/DemandControl'; // eslint-disable-next-line @typescript-eslint/no-var-requires const RestClient = require('node-rest-client').Client; export type Logger = null | undefined | ((data: string | null) => void); export interface SetSpecialModeRequestObject { state: 0 | 1 | '0' | '1'; kind: SpecialModeKind; } export interface DaikinACOptions { logger?: Logger; useGetToPost?: boolean; } export type ResponseHandler = (data: Error | string | Buffer, response?: unknown) => void; export type DaikinResponseCb<T> = (err: Error | null, ret: any | null, daikinResponse: T | null) => void; export class DaikinACRequest { get logger(): Logger | null { return this._logger; } set logger(value: Logger | null) { this._logger = value; } private _logger: Logger | null = null; private defaultParameters: { [key: string]: any } = {}; private readonly useGetToPost: boolean = false; private readonly ip: string; private restClient: any; public constructor(ip: string, options: DaikinACOptions) { this.ip = ip; if (options.logger !== undefined) { this.logger = options.logger; } if (options.useGetToPost) { this.useGetToPost = true; } this.restClient = new RestClient(); } public addDefaultParameter(key: string, value: any) { this.defaultParameters[key] = value; } public doGet(url: string, parameters: RequestDict, callback: ResponseHandler) { const reqParams = Object.assign({}, this.defaultParameters, parameters); const data: any = { parameters: reqParams, headers: { 'Content-Type': 'text/plain', 'User-Agent': 'DaikinOnlineController/2.4.2 CFNetwork/978.0.7 Darwin/18.6.0', Accept: '*/*', 'Accept-Language': 'de-de', 'Accept-Encoding': 'gzip, deflate', }, requestConfig: { timeout: 5000, //request timeout in milliseconds noDelay: true, //Enable/disable the Nagle algorithm keepAlive: false, //Enable/disable keep-alive functionalityidle socket. //keepAliveDelay: 1000 //and optionally set the initial delay before the first keepalive probe is sent }, responseConfig: { timeout: 5000, //response timeout }, }; if (this.logger) this.logger(`Call GET ${url} with ${JSON.stringify(reqParams)}`); const req = this.restClient.get(url, data, callback); req.on('requestTimeout', (req: XMLHttpRequest) => { if (this.logger) this.logger('request timeout'); req.abort(); callback(new Error(`Error while communicating with Daikin device: Timeout`)); }); req.on('responseTimeout', (_res: any) => { if (this.logger) this.logger('response timeout'); }); req.on('error', (err: any) => { let errMessage: string; if (err.code) { errMessage = err.code; } else if (err.message) { errMessage = err.message; } else { errMessage = err.toString(); } err.message = `Error while communicating with Daikin device: ${errMessage}`; callback(err); }); } public doPost(url: string, parameters: { [key: string]: any }, callback: ResponseHandler) { if (this.useGetToPost) { this.doGet(url, parameters, callback); return; } const reqParams = Object.assign({}, this.defaultParameters, parameters); const data = { data: reqParams, headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'User-Agent': 'DaikinOnlineController/2.4.2 CFNetwork/978.0.7 Darwin/18.6.0', Accept: '*/*', 'Accept-Language': 'de-de', 'Accept-Encoding': 'gzip, deflate', }, requestConfig: { timeout: 5000, //request timeout in milliseconds noDelay: true, //Enable/disable the Nagle algorithm keepAlive: false, //Enable/disable keep-alive functionalityidle socket. //keepAliveDelay: 1000 //and optionally set the initial delay before the first keepalive probe is sent }, responseConfig: { timeout: 5000, //response timeout }, }; if (this.logger) { this.logger(`Call POST ${url} with ${JSON.stringify(reqParams)}`); } const req = this.restClient.post(url, data, callback); req.on('requestTimeout', (req: XMLHttpRequest) => { if (this.logger) this.logger('request timeout'); req.abort(); }); req.on('responseTimeout', (_res: unknown) => { if (this.logger) this.logger('response timeout'); }); req.on('error', (err: any) => { if (err.code !== undefined) { err = err.code; } else if (err.message) { err = err.message; } else { err = err.toString(); } callback(new Error(`Error while communicating with Daikin device: ${err}`)); }); } public setACSpecialMode( obj: SetSpecialModeRequest | SetSpecialModeRequestObject, callback: DaikinResponseCb<SetCommandResponse>, ) { if (!(obj instanceof SetSpecialModeRequest)) { const state = typeof obj.state === 'string' ? parseInt(obj.state, 10) : obj.state; obj = new SetSpecialModeRequest(state, obj.kind); } const requestDict = obj.getRequestDict(); this.doPost(`http://${this.ip}/aircon/set_special_mode`, requestDict, (data, _res) => { const dict = DaikinDataParser.processResponse(data, callback, requestDict); if (dict !== null) SetCommandResponse.parseResponse(dict, callback); }); } public getACYearPowerExtended(callback: DaikinResponseCb<YearPowerExtendedResponse>) { this.doGet(`http://${this.ip}/aircon/get_year_power_ex`, {}, (data, _res) => { const dict = DaikinDataParser.processResponse(data, callback); if (dict !== null) YearPowerExtendedResponse.parseResponse(dict, callback); }); } public getCommonBasicInfo(callback: DaikinResponseCb<BasicInfoResponse>) { this.doGet(`http://${this.ip}/common/basic_info`, {}, (data, _response) => { const dict = DaikinDataParser.processResponse(data, callback); if (dict !== null) BasicInfoResponse.parseResponse(dict, callback); }); } public getCommonRemoteMethod(callback: DaikinResponseCb<RemoteMethodResponse>) { this.doGet(`http://${this.ip}/aircon/get_remote_method`, {}, (data, _response) => { const dict = DaikinDataParser.processResponse(data, callback); if (dict !== null) RemoteMethodResponse.parseResponse(dict, callback); }); } public setCommonLED(ledOn: boolean, callback: DaikinResponseCb<SetCommandResponse>) { const requestDict = { led: ledOn ? 1 : 0 }; this.doPost(`http://${this.ip}/common/set_led`, requestDict, (data, _response) => { const dict = DaikinDataParser.processResponse(data, callback, requestDict); if (dict !== null) SetCommandResponse.parseResponse(dict, callback); }); } public rebootAdapter(callback: DaikinResponseCb<SetCommandResponse>) { this.doPost(`http://${this.ip}/common/reboot`, {}, (data, _response) => { const dict = DaikinDataParser.processResponse(data, callback); if (dict !== null) SetCommandResponse.parseResponse(dict, callback); }); } public getACModelInfo(callback: DaikinResponseCb<ModelInfoResponse>) { this.doGet(`http://${this.ip}/aircon/get_model_info`, {}, (data, _response) => { const dict = DaikinDataParser.processResponse(data, callback); if (dict !== null) ModelInfoResponse.parseResponse(dict, callback); }); } public getACControlInfo(callback: DaikinResponseCb<ControlInfo>) { this.doGet(`http://${this.ip}/aircon/get_control_info`, {}, (data, _response) => { const dict = DaikinDataParser.processResponse(data, callback); if (dict !== null) ControlInfo.parseResponse(dict, callback); }); } public setACControlInfo(obj: ControlInfo, callback: DaikinResponseCb<SetCommandResponse>) { try { const requestDict = obj.getRequestDict(); this.doPost(`http://${this.ip}/aircon/set_control_info`, requestDict, (data, _response) => { const dict = DaikinDataParser.processResponse(data, callback, requestDict); if (dict !== null) SetCommandResponse.parseResponse(dict, callback); }); } catch (e) { callback(e instanceof Error ? e : new Error(e as string), null, null); } } public getACDemandControl(callback: DaikinResponseCb<DemandControl>) { this.doGet(`http://${this.ip}/aircon/get_demand_control`, {}, (data, _response) => { const dict = DaikinDataParser.processResponse(data, callback); if (dict !== null) DemandControl.parseResponse(dict, callback); }); } public setACDemandControl(obj: DemandControl, callback: DaikinResponseCb<SetCommandResponse>) { try { const requestDict = obj.getRequestDict(); this.doPost(`http://${this.ip}/aircon/set_demand_control`, requestDict, (data, _response) => { const dict = DaikinDataParser.processResponse(data, callback, requestDict); if (dict !== null) SetCommandResponse.parseResponse(dict, callback); }); } catch (e) { callback(e instanceof Error ? e : new Error(e as string), null, null); } } public getACSensorInfo(callback: DaikinResponseCb<SensorInfoResponse>) { this.doGet(`http://${this.ip}/aircon/get_sensor_info`, {}, (data, _response) => { const dict = DaikinDataParser.processResponse(data, callback); if (dict !== null) SensorInfoResponse.parseResponse(dict, callback); }); } public getACWeekPower(callback: DaikinResponseCb<WeekPowerResponse>) { this.doGet(`http://${this.ip}/aircon/get_week_power`, {}, (data, _response) => { const dict = DaikinDataParser.processResponse(data, callback); if (dict !== null) WeekPowerResponse.parseResponse(dict, callback); }); } public getACYearPower(callback: DaikinResponseCb<YearPowerResponse>) { if (this.logger) this.logger(`Call GET http://${this.ip}/aircon/get_year_power`); this.doGet(`http://${this.ip}/aircon/get_year_power`, {}, (data, _response) => { const dict = DaikinDataParser.processResponse(data, callback); if (dict !== null) YearPowerResponse.parseResponse(dict, callback); }); } public getACWeekPowerExtended(callback: DaikinResponseCb<WeekPowerExtendedResponse>) { if (this.logger) this.logger(`Call GET http://${this.ip}/aircon/get_week_power_ex`); this.doGet(`http://${this.ip}/aircon/get_week_power_ex`, {}, (data, _response) => { const dict = DaikinDataParser.processResponse(data, callback); if (dict !== null) WeekPowerExtendedResponse.parseResponse(dict, callback); }); } }