Skip to content

Commit

Permalink
chore: code push
Browse files Browse the repository at this point in the history
  • Loading branch information
baran.wang committed Feb 15, 2024
1 parent 910e70a commit 81a8ade
Show file tree
Hide file tree
Showing 13 changed files with 346 additions and 123 deletions.
1 change: 1 addition & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"semi": ["off"],
"comma-dangle": ["warn", "always-multiline"],
"dot-notation": "off",
"no-empty": "off",
"eqeqeq": "warn",
"curly": ["warn", "all"],
"brace-style": ["warn"],
Expand Down
6 changes: 4 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
"editor.rulers": [ 140 ],
"eslint.enable": true,
"cSpell.words": [
"Aqara"
]
"Aqara",
"Lumi"
],
"prettier.printWidth": 120
}
11 changes: 10 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"ui-src"
],
"devDependencies": {
"@types/lodash": "^4.14.202",
"@types/node": "^18.16.20",
"@typescript-eslint/eslint-plugin": "^5.62.0",
"@typescript-eslint/parser": "^5.62.0",
Expand All @@ -39,6 +40,7 @@
"typescript": "^4.9.5"
},
"dependencies": {
"axios": "^1.6.7"
"axios": "^1.6.7",
"lodash": "^4.17.21"
}
}
29 changes: 20 additions & 9 deletions src/accessories/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,35 @@ export class BaseAccessory {
constructor(readonly platform: AqaraHomebridgePlatform, readonly accessory: AqaraPlatformAccessory) {
const { deviceInfo } = this.accessory.context;
const { Characteristic, Service } = this.platform;
this.accessory
.getService(Service.AccessoryInformation)!
.setCharacteristic(Characteristic.Manufacturer, 'Aqara')
.setCharacteristic(Characteristic.Model, deviceInfo.model)
.setCharacteristic(Characteristic.SerialNumber, deviceInfo.did.split('.').pop()!.toUpperCase());
this.accessory
.getService(Service.AccessoryInformation)!
.setCharacteristic(Characteristic.Manufacturer, 'Aqara')
.setCharacteristic(Characteristic.Model, deviceInfo.model)
.setCharacteristic(Characteristic.SerialNumber, deviceInfo.did.split('.').pop()!.toUpperCase());
}

protected generateServices<T extends typeof Service>(services: T[]) {
this.services = services.map(
service => this.accessory.getService(service as any) || this.accessory.addService(service as any),
(service) => this.accessory.getService(service as any) || this.accessory.addService(service as any),
);
}

protected getResourceValue(resourceId: string) {
return this.platform.aqaraApi.getResourceValue(this.accessory.context.deviceInfo.did, [resourceId]);
const subjectId = this.accessory.context.deviceInfo.did;
return this.platform.aqaraApi.getResourceValue(subjectId, resourceId).then((res) => {
const item = res.find((item) => item.subjectId === subjectId && item.resourceId === resourceId);
if (!item) {
throw new Error('Resource not found');
}
return item;
});
}

protected setResourceValue(resourceId: string, value: string) {
return this.platform.aqaraApi.setResourceValue(this.accessory.context.deviceInfo.did, [{ resourceId, value }]);
try {
return this.platform.aqaraApi.setResourceValue(this.accessory.context.deviceInfo.did, resourceId, value);
} catch (error) {
return Promise.reject(error);
}
}
}
}
1 change: 1 addition & 0 deletions src/accessories/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './lumi.airer.acn02';
73 changes: 66 additions & 7 deletions src/accessories/lumi.airer.acn02.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import { BaseAccessory } from './base';

export class LumiAirerAcn02 extends BaseAccessory {

constructor(platform, accessory) {
super(platform, accessory);

this.init();

}

init() {
Expand All @@ -15,11 +13,72 @@ export class LumiAirerAcn02 extends BaseAccessory {

this.services[0]
.getCharacteristic(this.platform.Characteristic.On)
.onGet(this.getLightbulbOn.bind(this));
.onGet(this.getLightbulbOn.bind(this))
.onSet(this.setLightbulbOn.bind(this));

this.services[1]
.getCharacteristic(this.platform.Characteristic.CurrentPosition)
.onGet(this.getCurrentPosition.bind(this))
.onSet(this.setCurrentPosition.bind(this));
}

lightbulbOn = false;

async getLightbulbOn() {
try {
const { value } = await this.getResourceValue('14.2.85');
this.lightbulbOn = value === '1';
} catch (error) {}
return this.lightbulbOn;
}

async setLightbulbOn(value) {
try {
await this.setResourceValue('14.2.85', value ? '1' : '0');
this.lightbulbOn = value;
} catch (error) {}
}

currentPosition = 0;

async getCurrentPosition() {
try {
const { value } = await this.getResourceValue('1.1.85');
this.currentPosition = parseInt(value);
} catch (error) {}
return this.currentPosition;
}

async setCurrentPosition(value) {
try {
await this.setResourceValue('1.1.85', value.toString());
this.currentPosition = value;
} catch (error) {}
}

positionState = this.platform.Characteristic.PositionState.STOPPED;

private positionStateMap = {
'1': this.platform.Characteristic.PositionState.DECREASING,
'2': this.platform.Characteristic.PositionState.INCREASING,
'0': this.platform.Characteristic.PositionState.STOPPED,
};

async getPositionState() {
try {
const { value } = await this.getResourceValue('14.1.85');
this.positionState = this.positionStateMap[value];
} catch (error) {}
return this.positionState;
}

getLightbulbOn() {
this.getResourceValue('14.2.85');
return true;
async setPositionState(value) {
try {
const [aqaraValue] = Object.entries(this.positionStateMap).find(([_, val]) => val === value) ?? [];
if (aqaraValue) {
await this.setResourceValue('14.1.85', aqaraValue);
this.positionState = value;
}
} catch (error) {}
}
}
}
41 changes: 41 additions & 0 deletions src/api/batch-requester.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
type RequestFunction<T1, R> = (args: T1) => Promise<R>;
type MergeFunction<T1, T2> = (requests: T2[]) => T1;

interface RequestParams<T> {
args: T;
resolve: (value: any) => void;
reject: (reason?: any) => void;
}
export class BatchRequester<T1, T2 = T1, R = any> {
private requests: RequestParams<T2>[] = [];
private timer: NodeJS.Timeout | null = null;

constructor(
private readonly requestFunction: RequestFunction<T1, R>,
private readonly mergeFunction: MergeFunction<T1, T2>,
private readonly waitTime: number = 100,
) {}

request(args: T2): Promise<R> {
return new Promise((resolve, reject) => {
this.requests.push({ args, resolve, reject });

if (!this.timer) {
this.timer = setTimeout(async () => {
this.timer = null;

const requests = this.requests;
this.requests = [];

try {
const mergedArgs = this.mergeFunction(requests.map((request) => request.args));
const result = await this.requestFunction(mergedArgs);
requests.forEach(({ resolve }) => resolve(result));
} catch (error) {
requests.forEach(({ reject }) => reject(error));
}
}, this.waitTime);
}
});
}
}
Loading

0 comments on commit 81a8ade

Please sign in to comment.