diff options
| author | Li Zhineng <[email protected]> | 2025-07-18 14:53:03 +0800 |
|---|---|---|
| committer | Li Zhineng <[email protected]> | 2025-07-18 14:53:28 +0800 |
| commit | 0654a9093510f88502bb5e92aa9af41dd319853c (patch) | |
| tree | 3285625e77a41cd6e789bdc620c3621e73085403 /packages | |
| parent | 3597fb51743f3723cc7d87a049442d574a74a856 (diff) | |
| download | airmx-0654a9093510f88502bb5e92aa9af41dd319853c.tar.gz airmx-0654a9093510f88502bb5e92aa9af41dd319853c.zip | |
control a specific device
Diffstat (limited to 'packages')
| -rw-r--r-- | packages/airmx/src/airmx.ts | 12 | ||||
| -rw-r--r-- | packages/airmx/src/eagle.test.ts | 8 | ||||
| -rw-r--r-- | packages/airmx/src/eagle.ts | 98 | ||||
| -rw-r--r-- | packages/airmx/src/types.ts | 19 |
4 files changed, 125 insertions, 12 deletions
diff --git a/packages/airmx/src/airmx.ts b/packages/airmx/src/airmx.ts index e4789f0..5e933ba 100644 --- a/packages/airmx/src/airmx.ts +++ b/packages/airmx/src/airmx.ts @@ -10,7 +10,7 @@ import type { import type { CommandMessage } from './messages.js' import { EagleControlMesasge } from './messages.js' -import { EagleStatus } from './eagle.js' +import { EagleController, EagleStatus } from './eagle.js' import { Signer } from './util.js' import { SnowStatus } from './snow.js' @@ -169,4 +169,14 @@ export class Airmx { getEagleStatus(deviceId: number) { return this.#eagles.get(deviceId) } + + /** + * Specify an AIRMX Pro device. + * + * @param deviceId - The device ID. + * @returns The device controller. + */ + device(deviceId: number) { + return new EagleController(this, deviceId) + } } diff --git a/packages/airmx/src/eagle.test.ts b/packages/airmx/src/eagle.test.ts index 84c5ebb..2af1bd4 100644 --- a/packages/airmx/src/eagle.test.ts +++ b/packages/airmx/src/eagle.test.ts @@ -1,5 +1,7 @@ +import type { Message, EagleStatusData } from './types.js' + import { EagleStatus } from './eagle.js' -import { EagleMode, EagleStatusData } from './types.js' +import { EagleMode } from './types.js' test('from parses message to eagle status', () => { const status = EagleStatus.from(12345, createStubStatusData()) @@ -70,7 +72,9 @@ test('isHeaterOff determines if the heater is off', () => { expect(status.isHeaterOn()).toBe(false) }) -const createStubStatusData = (data: Partial<EagleStatusData> = {}) => ({ +const createStubStatusData = ( + data: Partial<EagleStatusData> = {}, +): Message<EagleStatusData> => ({ cmdId: 210, data: { cadr: 17, diff --git a/packages/airmx/src/eagle.ts b/packages/airmx/src/eagle.ts index 4de587c..87dd1e7 100644 --- a/packages/airmx/src/eagle.ts +++ b/packages/airmx/src/eagle.ts @@ -1,4 +1,6 @@ -import type { Message, EagleStatusData } from './types.js' +import type { Message, EagleStatusData, EagleControlData } from './types.js' + +import { Airmx } from './airmx.js' import { EagleMode } from './types.js' export class EagleStatus { @@ -108,4 +110,98 @@ export class EagleStatus { 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: 1 }) + } + + off() { + this.#send({ power: 0 }) + } + + heatOn() { + this.#send({ heatStatus: 1 }) + } + + heatOff() { + this.#send({ heatStatus: 0 }) + } + + denoiseOn() { + this.#send({ denoise: 1 }) + } + + denoiseOff() { + this.#send({ denoise: 0 }) + } + + cadr(cadr: number) { + this.#send({ + power: 1, + mode: EagleMode.Manual, + cadr, + }) + } + + /** + * Automate the fan speed based on the data from the air monitor. + */ + ai() { + this.#send({ + power: 1, + mode: EagleMode.Ai, + }) + } + + /** + * Activate silent mode to minimize fan noise. + */ + silent() { + this.#send({ + power: 1, + mode: EagleMode.Silent, + }) + } + + /** + * Activate turbo mode for optimum air purification. + */ + turbo() { + this.#send({ + power: 1, + 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<EagleControlData>) { + this.airmx.control(this.deviceId, { + ...this.status().toControlData(), + ...data, + }) + } } diff --git a/packages/airmx/src/types.ts b/packages/airmx/src/types.ts index ef7ab89..5c28d90 100644 --- a/packages/airmx/src/types.ts +++ b/packages/airmx/src/types.ts @@ -31,13 +31,20 @@ export interface Message<T> { sig: string } +export enum EagleMode { + Manual = 0, + Ai, + Silent, + Turbo, +} + export interface EagleStatusData { version: string - power: number - mode: number + power: 0 | 1 + mode: EagleMode status: number - denoise: number - heatStatus: number + denoise: 0 | 1 + heatStatus: 0 | 1 cadr: number prm: number diffPressure1: number @@ -51,10 +58,6 @@ export interface EagleStatusData { hepaPercent: number } -export enum EagleMode { - Silent = 2, -} - export enum SensorState { Sampling = 'sampling', } |
