From e6279ae486eef2d549a4b5dd15e4e446d2180dc7 Mon Sep 17 00:00:00 2001 From: Li Zhineng Date: Sat, 19 Jul 2025 15:35:02 +0800 Subject: give up monorepo --- src/eagle.ts | 207 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 207 insertions(+) create mode 100644 src/eagle.ts (limited to 'src/eagle.ts') diff --git a/src/eagle.ts b/src/eagle.ts new file mode 100644 index 0000000..dbe74cc --- /dev/null +++ b/src/eagle.ts @@ -0,0 +1,207 @@ +import type { Message, EagleStatusData, EagleControlData } from './types.js' + +import { Airmx } from './airmx.js' +import { EagleMode, Switch } from './types.js' + +export class EagleStatus { + constructor( + public readonly deviceId: number, + public readonly message: Message, + ) {} + + static commandId() { + return 210 + } + + static from(deviceId: number, message: Message) { + if (message.cmdId !== this.commandId()) { + throw new Error( + `Eagle status expects a message with command ID ${this.commandId()}.`, + ) + } + + return new this(deviceId, message) + } + + get power() { + return this.message.data.power + } + + isOn() { + return this.power === Switch.On + } + + isOff() { + return !this.isOn() + } + + get mode() { + return this.message.data.mode + } + + isSilentMode() { + return this.mode === EagleMode.Silent + } + + get status() { + return this.message.data.status + } + + get denoise() { + return this.message.data.denoise + } + + isDenoiseOn() { + return this.denoise === Switch.On + } + + isDenoiseOff() { + return !this.isDenoiseOn() + } + + get heatStatus() { + return this.message.data.heatStatus + } + + isHeaterOn() { + return this.heatStatus === Switch.On + } + + isHeaterOff() { + return !this.isHeaterOn() + } + + get cadr() { + return this.message.data.cadr + } + + get prm() { + return this.message.data.prm + } + + get temperature() { + return this.message.data.t0 + } + + get g4Id() { + return this.message.data.g4Id + } + + get g4Percent() { + return this.message.data.g4Percent + } + + get carbonId() { + return this.message.data.carbonId + } + + get carbonPercent() { + return this.message.data.carbonPercent + } + + get hepaId() { + return this.message.data.hepaId + } + + get hepaPercent() { + return this.message.data.hepaPercent + } + + get version() { + return this.message.data.version + } + + toControlData(): EagleControlData { + const { power, heatStatus, mode, cadr, denoise } = this.message.data + return { power, heatStatus, mode, cadr, denoise } + } +} + +export class EagleController { + constructor( + private readonly airmx: Airmx, + private readonly deviceId: number, + ) {} + + on() { + this.#send({ power: Switch.On }) + } + + off() { + this.#send({ power: Switch.Off }) + } + + heatOn() { + this.#send({ heatStatus: Switch.On }) + } + + heatOff() { + this.#send({ heatStatus: Switch.Off }) + } + + denoiseOn() { + this.#send({ denoise: Switch.On }) + } + + denoiseOff() { + this.#send({ denoise: Switch.Off }) + } + + cadr(cadr: number) { + this.#send({ + power: Switch.On, + mode: EagleMode.Manual, + cadr, + }) + } + + /** + * Automate the fan speed based on the data from the air monitor. + */ + ai() { + this.#send({ + power: Switch.On, + mode: EagleMode.Ai, + }) + } + + /** + * Activate silent mode to minimize fan noise. + */ + silent() { + this.#send({ + power: Switch.On, + mode: EagleMode.Silent, + }) + } + + /** + * Activate turbo mode for optimum air purification. + */ + turbo() { + this.#send({ + power: Switch.On, + mode: EagleMode.Turbo, + cadr: 100, + }) + } + + status() { + const status = this.airmx.getEagleStatus(this.deviceId) + + if (status === undefined) { + throw new Error( + `Could not retrieve the status of the device with ID ${this.deviceId}.`, + ) + } + + return status + } + + #send(data: Partial) { + this.airmx.control(this.deviceId, { + ...this.status().toControlData(), + ...data, + }) + } +} -- cgit v1.2.3