homebridge-aqara-ir-controller 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +57 -0
- package/config.schema.json +81 -0
- package/dist/accessories/AbstractAccessory.d.ts +11 -0
- package/dist/accessories/AbstractAccessory.d.ts.map +1 -0
- package/dist/accessories/AbstractAccessory.js +18 -0
- package/dist/accessories/AbstractAccessory.js.map +1 -0
- package/dist/accessories/IrACAccessory.d.ts +54 -0
- package/dist/accessories/IrACAccessory.d.ts.map +1 -0
- package/dist/accessories/IrACAccessory.js +174 -0
- package/dist/accessories/IrACAccessory.js.map +1 -0
- package/dist/accessories/index.d.ts +4 -0
- package/dist/accessories/index.d.ts.map +1 -0
- package/dist/accessories/index.js +8 -0
- package/dist/accessories/index.js.map +1 -0
- package/dist/homebridge-ui/public/index.html +111 -0
- package/dist/homebridge-ui/public/main.css +0 -0
- package/dist/homebridge-ui/server.d.ts +2 -0
- package/dist/homebridge-ui/server.d.ts.map +1 -0
- package/dist/homebridge-ui/server.js +94 -0
- package/dist/homebridge-ui/server.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/AqaraAPI.d.ts +46 -0
- package/dist/lib/AqaraAPI.d.ts.map +1 -0
- package/dist/lib/AqaraAPI.js +216 -0
- package/dist/lib/AqaraAPI.js.map +1 -0
- package/dist/lib/help.d.ts +2 -0
- package/dist/lib/help.d.ts.map +1 -0
- package/dist/lib/help.js +20 -0
- package/dist/lib/help.js.map +1 -0
- package/dist/platform.d.ts +16 -0
- package/dist/platform.d.ts.map +1 -0
- package/dist/platform.js +108 -0
- package/dist/platform.js.map +1 -0
- package/dist/settings.d.ts +9 -0
- package/dist/settings.d.ts.map +1 -0
- package/dist/settings.js +12 -0
- package/dist/settings.js.map +1 -0
- package/package.json +45 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Vladan Stanković
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
<img alt="Logo" src="https://github.com/homebridge/branding/raw/latest/logos/homebridge-wordmark-logo-vertical.png" width="150">
|
|
2
|
+
|
|
3
|
+
# Homebridge Aqara Ir AC
|
|
4
|
+
|
|
5
|
+
## Introduction
|
|
6
|
+
Since Aqara is not willing to expose IR based Controllers to to HomeKit, I have decided to hack up this Homebridge plugin...
|
|
7
|
+
Took me a couple of hours, so don't expect a smooth experience, but I am willing to fix the issues if someone reports them. :)
|
|
8
|
+
|
|
9
|
+
This plugin currently works with IR AC only, but can easily be expanded for the rest of the Aqara devices.
|
|
10
|
+
I don't think that it makes sense since Aqara already has HomeKit integration for everything else.
|
|
11
|
+
|
|
12
|
+
Keep in mind that this will NOT work for AC Mode Ird control on new Aqara hubs such as M3, since Aqara API won't even list this as a device.
|
|
13
|
+
It works only for manually configured Ird AC controls.
|
|
14
|
+
|
|
15
|
+
It makes sense for plugin this to be expanded to handle any other Ird control, but I didn't need this.
|
|
16
|
+
I might accept wishes, and I will definitively accept pull requests for expansions.
|
|
17
|
+
|
|
18
|
+
## Setup
|
|
19
|
+
Setup is not as straight forward as I would like, but the best one I could hack up with Homebridges UI limitations.
|
|
20
|
+
|
|
21
|
+
Don't let many of fields to confuse you.
|
|
22
|
+
|
|
23
|
+
Since Aqara is charging developers for API access after some request numbers have been reached, I have decided to make it a bit more complicated so that nobody has to pay.
|
|
24
|
+
|
|
25
|
+
Aqara does offer EVERYONE a free Demo application, that everyone can use.
|
|
26
|
+
|
|
27
|
+
In order to setup an account, go to <a href="https://developer.aqara.com">Aqara Developer website</a> sign up and log into console.
|
|
28
|
+
|
|
29
|
+
Select Manage Project on the left side, and view Details of the Demo Application.
|
|
30
|
+
|
|
31
|
+
Demo app has different keys for different server regions.
|
|
32
|
+
|
|
33
|
+
Select appropriate region in plugin config, and copy the necessary keys of the appropriate region of the demo app.
|
|
34
|
+
|
|
35
|
+
In the username field of the plugin configuration enter your Aqara username, email or mobile number.
|
|
36
|
+
|
|
37
|
+
If you now how to generate access token, you can paste it directly and hit bottom save button.
|
|
38
|
+
|
|
39
|
+
If not, click Proceed, and you will be provided with a field to enter auth code that you will receive over email or SMS.
|
|
40
|
+
|
|
41
|
+
Once you enter the code plugin will authenticate.
|
|
42
|
+
|
|
43
|
+
The only thing left for you is to select Home to integrate with (if you have multiple), and plugin will configure your devices.
|
|
44
|
+
|
|
45
|
+
If home is not selected IR AC remotes from ALL homes will be added.
|
|
46
|
+
|
|
47
|
+
## Limitations
|
|
48
|
+
Right now plugin is not listening to Aqara events, so if you make changes with Aqara app, it will take some time for them to sync.
|
|
49
|
+
Handles Celsius only
|
|
50
|
+
Handles AC control only
|
|
51
|
+
Doesn't have an option to set up cooling/heating range, it's fixed to 10 - 30
|
|
52
|
+
|
|
53
|
+
## Future plans
|
|
54
|
+
To implement this listener at one point.
|
|
55
|
+
|
|
56
|
+
It would be cool to make a better interface with better UX.
|
|
57
|
+
Homebridge has a terrible way to build interface, especially custom interface, and my plan was to hack this in a couple of hours, so I can't really investigate a way to improve this...
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
{
|
|
2
|
+
"pluginAlias": "AqaraIrController",
|
|
3
|
+
"pluginType": "platform",
|
|
4
|
+
"headerDisplay": "This plugin is currently experimental and under development.",
|
|
5
|
+
"footerDisplay": "For help please see the [homepage](https://github.com/vaxter/homebridge-aqara-ir-controller)",
|
|
6
|
+
"singular": true,
|
|
7
|
+
"customUi": true,
|
|
8
|
+
"customUiPath": "./dist/homebridge-ui",
|
|
9
|
+
"schema": {
|
|
10
|
+
"type": "object",
|
|
11
|
+
"properties": {
|
|
12
|
+
"region": {
|
|
13
|
+
"title": "API server region",
|
|
14
|
+
"type": "string",
|
|
15
|
+
"required": true,
|
|
16
|
+
"enum": [
|
|
17
|
+
"cn",
|
|
18
|
+
"us",
|
|
19
|
+
"kr",
|
|
20
|
+
"ru",
|
|
21
|
+
"de",
|
|
22
|
+
"sg"
|
|
23
|
+
],
|
|
24
|
+
"default": "cn",
|
|
25
|
+
"description": "Select region of Aqara API server"
|
|
26
|
+
},
|
|
27
|
+
"lang": {
|
|
28
|
+
"title": "API response Language",
|
|
29
|
+
"type": "string",
|
|
30
|
+
"required": true,
|
|
31
|
+
"enum": [
|
|
32
|
+
"en",
|
|
33
|
+
"zh"
|
|
34
|
+
],
|
|
35
|
+
"default": "en",
|
|
36
|
+
"description": "Select language of the API response"
|
|
37
|
+
},
|
|
38
|
+
"appId": {
|
|
39
|
+
"title": "AppId",
|
|
40
|
+
"type": "string",
|
|
41
|
+
"required": true
|
|
42
|
+
},
|
|
43
|
+
"keyId": {
|
|
44
|
+
"title": "KeyId",
|
|
45
|
+
"type": "string",
|
|
46
|
+
"required": true
|
|
47
|
+
},
|
|
48
|
+
"appKey": {
|
|
49
|
+
"title": "appKey",
|
|
50
|
+
"type": "string",
|
|
51
|
+
"required": true
|
|
52
|
+
},
|
|
53
|
+
"version": {
|
|
54
|
+
"title": "appKey",
|
|
55
|
+
"type": "string",
|
|
56
|
+
"default": "v3.0",
|
|
57
|
+
"required": true
|
|
58
|
+
},
|
|
59
|
+
"username": {
|
|
60
|
+
"title": "Aqara username, email or mobile number",
|
|
61
|
+
"type": "string",
|
|
62
|
+
"required": true
|
|
63
|
+
},
|
|
64
|
+
"positionId": {
|
|
65
|
+
"title": "positionId of Aqara Home",
|
|
66
|
+
"type": "string",
|
|
67
|
+
"required": false
|
|
68
|
+
},
|
|
69
|
+
"accessToken": {
|
|
70
|
+
"title": "Auth Token",
|
|
71
|
+
"type": "string",
|
|
72
|
+
"required": false
|
|
73
|
+
},
|
|
74
|
+
"refreshToken": {
|
|
75
|
+
"title": "Refresh Token",
|
|
76
|
+
"type": "string",
|
|
77
|
+
"required": false
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { AqaraIrControllerPlatform } from '../platform';
|
|
2
|
+
import { Service, PlatformAccessory, Characteristic, UnknownContext } from 'homebridge';
|
|
3
|
+
export declare abstract class AbstractAccessory {
|
|
4
|
+
protected readonly platform: AqaraIrControllerPlatform;
|
|
5
|
+
protected readonly accessory: PlatformAccessory;
|
|
6
|
+
protected readonly data: UnknownContext;
|
|
7
|
+
protected Service: typeof Service;
|
|
8
|
+
protected Characteristic: typeof Characteristic;
|
|
9
|
+
protected constructor(platform: AqaraIrControllerPlatform, accessory: PlatformAccessory, data?: UnknownContext);
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=AbstractAccessory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AbstractAccessory.d.ts","sourceRoot":"","sources":["../../src/accessories/AbstractAccessory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,yBAAyB,EAAC,MAAM,aAAa,CAAC;AACtD,OAAO,EAAC,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,cAAc,EAAC,MAAM,YAAY,CAAC;AAEtF,8BAAsB,iBAAiB;IAKnC,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,yBAAyB;IACtD,SAAS,CAAC,QAAQ,CAAC,SAAS,EAAE,iBAAiB;IAC/C,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,cAAc;IANzC,SAAS,CAAC,OAAO,EAAE,OAAO,OAAO,CAAC;IAClC,SAAS,CAAC,cAAc,EAAE,OAAO,cAAc,CAAC;IAEhD,SAAS,aACY,QAAQ,EAAE,yBAAyB,EACnC,SAAS,EAAE,iBAAiB,EAC5B,IAAI,GAAE,cAAmB;CAW/C"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AbstractAccessory = void 0;
|
|
4
|
+
class AbstractAccessory {
|
|
5
|
+
constructor(platform, accessory, data = {}) {
|
|
6
|
+
this.platform = platform;
|
|
7
|
+
this.accessory = accessory;
|
|
8
|
+
this.data = data;
|
|
9
|
+
this.Service = this.platform.api.hap.Service;
|
|
10
|
+
this.Characteristic = this.platform.api.hap.Characteristic;
|
|
11
|
+
this.accessory.getService(this.platform.api.hap.Service.AccessoryInformation)
|
|
12
|
+
.setCharacteristic(this.platform.api.hap.Characteristic.Manufacturer, 'Aqara')
|
|
13
|
+
.setCharacteristic(this.platform.api.hap.Characteristic.Model, 'Aqara Ir Controller')
|
|
14
|
+
.setCharacteristic(this.platform.api.hap.Characteristic.SerialNumber, '42');
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
exports.AbstractAccessory = AbstractAccessory;
|
|
18
|
+
//# sourceMappingURL=AbstractAccessory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AbstractAccessory.js","sourceRoot":"","sources":["../../src/accessories/AbstractAccessory.ts"],"names":[],"mappings":";;;AAGA,MAAsB,iBAAiB;IAIrC,YACqB,QAAmC,EACnC,SAA4B,EAC5B,OAAuB,EAAE;QAFzB,aAAQ,GAAR,QAAQ,CAA2B;QACnC,cAAS,GAAT,SAAS,CAAmB;QAC5B,SAAI,GAAJ,IAAI,CAAqB;QAG5C,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC;QAC7C,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,cAAc,CAAC;QAE3D,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,oBAAoB,CAAE;aAC3E,iBAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,cAAc,CAAC,YAAY,EAAE,OAAO,CAAC;aAC7E,iBAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,cAAc,CAAC,KAAK,EAAE,qBAAqB,CAAC;aACpF,iBAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,cAAc,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;IAChF,CAAC;CACF;AAlBD,8CAkBC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { PlatformAccessory, UnknownContext } from 'homebridge';
|
|
2
|
+
import { AqaraIrControllerPlatform } from '../platform';
|
|
3
|
+
import { AbstractAccessory } from './AbstractAccessory';
|
|
4
|
+
export interface State {
|
|
5
|
+
temperature: number;
|
|
6
|
+
mode: number;
|
|
7
|
+
}
|
|
8
|
+
export declare class IrACAccessory extends AbstractAccessory {
|
|
9
|
+
protected readonly platform: AqaraIrControllerPlatform;
|
|
10
|
+
protected readonly accessory: PlatformAccessory;
|
|
11
|
+
protected readonly data: UnknownContext;
|
|
12
|
+
private readonly _primaryService;
|
|
13
|
+
private _state;
|
|
14
|
+
constructor(platform: AqaraIrControllerPlatform, accessory: PlatformAccessory, data: UnknownContext);
|
|
15
|
+
private _modeToState;
|
|
16
|
+
private _stateToMode;
|
|
17
|
+
private _stateToAqaraString;
|
|
18
|
+
private _parseAqaraState;
|
|
19
|
+
private _getAqaraInfo;
|
|
20
|
+
private _sendStateToAqara;
|
|
21
|
+
/**
|
|
22
|
+
* Handle requests to get the current value of the "Current Heating Cooling State" characteristic
|
|
23
|
+
*/
|
|
24
|
+
handleCurrentHeatingCoolingStateGet(): number;
|
|
25
|
+
/**
|
|
26
|
+
* Handle requests to get the current value of the "Target Heating Cooling State" characteristic
|
|
27
|
+
*/
|
|
28
|
+
handleTargetHeatingCoolingStateGet(): number;
|
|
29
|
+
/**
|
|
30
|
+
* Handle requests to set the "Target Heating Cooling State" characteristic
|
|
31
|
+
*/
|
|
32
|
+
handleTargetHeatingCoolingStateSet(value: any): void;
|
|
33
|
+
/**
|
|
34
|
+
* Handle requests to get the current value of the "Current Temperature" characteristic
|
|
35
|
+
*/
|
|
36
|
+
handleCurrentTemperatureGet(): number;
|
|
37
|
+
/**
|
|
38
|
+
* Handle requests to get the current value of the "Target Temperature" characteristic
|
|
39
|
+
*/
|
|
40
|
+
handleTargetTemperatureGet(): number;
|
|
41
|
+
/**
|
|
42
|
+
* Handle requests to set the "Target Temperature" characteristic
|
|
43
|
+
*/
|
|
44
|
+
handleTargetTemperatureSet(value: any): void;
|
|
45
|
+
/**
|
|
46
|
+
* Handle requests to get the current value of the "Temperature Display Units" characteristic
|
|
47
|
+
*/
|
|
48
|
+
handleTemperatureDisplayUnitsGet(): number;
|
|
49
|
+
/**
|
|
50
|
+
* Handle requests to set the "Temperature Display Units" characteristic
|
|
51
|
+
*/
|
|
52
|
+
handleTemperatureDisplayUnitsSet(value: any): void;
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=IrACAccessory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IrACAccessory.d.ts","sourceRoot":"","sources":["../../src/accessories/IrACAccessory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,iBAAiB,EAAW,cAAc,EAAC,MAAM,YAAY,CAAC;AAEtE,OAAO,EAAC,yBAAyB,EAAC,MAAM,aAAa,CAAC;AACtD,OAAO,EAAC,iBAAiB,EAAC,MAAM,qBAAqB,CAAC;AAEtD,MAAM,WAAW,KAAK;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,qBAAa,aAAc,SAAQ,iBAAiB;IAMhD,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,yBAAyB;IACtD,SAAS,CAAC,QAAQ,CAAC,SAAS,EAAE,iBAAiB;IAC/C,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,cAAc;IAPzC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAU;IAE1C,OAAO,CAAC,MAAM,CAAqF;gBAG9E,QAAQ,EAAE,yBAAyB,EACnC,SAAS,EAAE,iBAAiB,EAC5B,IAAI,EAAE,cAAc;IA6CzC,OAAO,CAAC,YAAY;IAapB,OAAO,CAAC,YAAY;IAWpB,OAAO,CAAC,mBAAmB;IAM3B,OAAO,CAAC,gBAAgB;IA6BxB,OAAO,CAAC,aAAa;IAerB,OAAO,CAAC,iBAAiB;IAYzB;;OAEG;IACH,mCAAmC;IAMnC;;OAEG;IACH,kCAAkC;IAMlC;;OAEG;IACH,kCAAkC,CAAC,KAAK,KAAA;IAQxC;;OAEG;IACH,2BAA2B;IAO3B;;OAEG;IACH,0BAA0B;IAM1B;;OAEG;IACH,0BAA0B,CAAC,KAAK,KAAA;IAQhC;;OAEG;IACH,gCAAgC;IAMhC;;OAEG;IACH,gCAAgC,CAAC,KAAK,KAAA;CAGvC"}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.IrACAccessory = void 0;
|
|
4
|
+
const AbstractAccessory_1 = require("./AbstractAccessory");
|
|
5
|
+
class IrACAccessory extends AbstractAccessory_1.AbstractAccessory {
|
|
6
|
+
constructor(platform, accessory, data) {
|
|
7
|
+
super(platform, accessory, data);
|
|
8
|
+
this.platform = platform;
|
|
9
|
+
this.accessory = accessory;
|
|
10
|
+
this.data = data;
|
|
11
|
+
this._state = { temperature: 23, mode: this.Characteristic.TargetHeatingCoolingState.OFF };
|
|
12
|
+
this._primaryService = this.accessory.getService(this.platform.api.hap.Service.Thermostat) || this.accessory.addService(this.platform.api.hap.Service.Thermostat);
|
|
13
|
+
this._primaryService.getCharacteristic(this.Characteristic.CurrentHeatingCoolingState)
|
|
14
|
+
.onGet(this.handleCurrentHeatingCoolingStateGet.bind(this));
|
|
15
|
+
this._primaryService.getCharacteristic(this.Characteristic.TargetHeatingCoolingState)
|
|
16
|
+
.onGet(this.handleTargetHeatingCoolingStateGet.bind(this))
|
|
17
|
+
.onSet(this.handleTargetHeatingCoolingStateSet.bind(this));
|
|
18
|
+
this._primaryService.getCharacteristic(this.Characteristic.CurrentTemperature)
|
|
19
|
+
.onGet(this.handleCurrentTemperatureGet.bind(this));
|
|
20
|
+
this._primaryService.getCharacteristic(this.Characteristic.TargetTemperature)
|
|
21
|
+
.onGet(this.handleTargetTemperatureGet.bind(this))
|
|
22
|
+
.onSet(this.handleTargetTemperatureSet.bind(this));
|
|
23
|
+
this._primaryService.getCharacteristic(this.Characteristic.TemperatureDisplayUnits)
|
|
24
|
+
.onGet(this.handleTemperatureDisplayUnitsGet.bind(this))
|
|
25
|
+
.onSet(this.handleTemperatureDisplayUnitsSet.bind(this));
|
|
26
|
+
this._primaryService.getCharacteristic(this.Characteristic.CoolingThresholdTemperature)
|
|
27
|
+
.setProps({
|
|
28
|
+
minValue: 10,
|
|
29
|
+
maxValue: 30,
|
|
30
|
+
minStep: 1,
|
|
31
|
+
});
|
|
32
|
+
this._primaryService.getCharacteristic(this.Characteristic.HeatingThresholdTemperature)
|
|
33
|
+
.setProps({
|
|
34
|
+
minValue: 10,
|
|
35
|
+
maxValue: 30,
|
|
36
|
+
minStep: 1,
|
|
37
|
+
});
|
|
38
|
+
this._getAqaraInfo(this.data.did).then((state) => {
|
|
39
|
+
this._state = state;
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
_modeToState(mode) {
|
|
43
|
+
switch (mode) {
|
|
44
|
+
case 'M0':
|
|
45
|
+
return this.Characteristic.TargetHeatingCoolingState.COOL;
|
|
46
|
+
case 'M1':
|
|
47
|
+
return this.Characteristic.TargetHeatingCoolingState.HEAT;
|
|
48
|
+
case 'M2':
|
|
49
|
+
return this.Characteristic.TargetHeatingCoolingState.AUTO;
|
|
50
|
+
default:
|
|
51
|
+
return this.Characteristic.TargetHeatingCoolingState.OFF;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
_stateToMode(state) {
|
|
55
|
+
switch (state) {
|
|
56
|
+
case this.Characteristic.TargetHeatingCoolingState.HEAT:
|
|
57
|
+
return 'M1';
|
|
58
|
+
case this.Characteristic.TargetHeatingCoolingState.COOL:
|
|
59
|
+
return 'M0';
|
|
60
|
+
default:
|
|
61
|
+
return 'M2';
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
_stateToAqaraString() {
|
|
65
|
+
const P = this._state.mode === this.Characteristic.TargetHeatingCoolingState.OFF ? 'P1' : 'P0';
|
|
66
|
+
const M = this._stateToMode(this._state.mode);
|
|
67
|
+
return `${P}_${M}_T${Math.floor(this._state.temperature)}_S0_D0`;
|
|
68
|
+
}
|
|
69
|
+
_parseAqaraState(state) {
|
|
70
|
+
this.platform.log.debug('Parsing Aqara state: ', state);
|
|
71
|
+
const split = state.split('_');
|
|
72
|
+
let P = false;
|
|
73
|
+
let T = 23;
|
|
74
|
+
let M = this.Characteristic.CurrentHeatingCoolingState.OFF;
|
|
75
|
+
split.forEach(value => {
|
|
76
|
+
if (value[0] === 'P') {
|
|
77
|
+
P = !parseInt(value[1]);
|
|
78
|
+
}
|
|
79
|
+
if (value[0] === 'M') {
|
|
80
|
+
M = !P ? this.Characteristic.CurrentHeatingCoolingState.OFF : this._modeToState(value);
|
|
81
|
+
}
|
|
82
|
+
if (value[0] === 'T') {
|
|
83
|
+
T = parseInt(value.substring(1));
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
return {
|
|
87
|
+
mode: M,
|
|
88
|
+
temperature: T,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
_getAqaraInfo(did) {
|
|
92
|
+
return this.platform.aqara.call('query.ir.acState', {
|
|
93
|
+
did,
|
|
94
|
+
}).then(data => {
|
|
95
|
+
return this._parseAqaraState(data.result.acState);
|
|
96
|
+
}, (err) => {
|
|
97
|
+
this.platform.log.error('Unable to fetch Aqara response state: ', err);
|
|
98
|
+
return {
|
|
99
|
+
mode: 0,
|
|
100
|
+
temperature: 23,
|
|
101
|
+
};
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
_sendStateToAqara() {
|
|
105
|
+
this.platform.aqara.call('write.ir.click', {
|
|
106
|
+
did: this.data.did,
|
|
107
|
+
brandId: this.data.brandId,
|
|
108
|
+
controllerId: this.data.controllerId,
|
|
109
|
+
isAcMatch: 1,
|
|
110
|
+
acKey: this._stateToAqaraString(),
|
|
111
|
+
}).then(data => {
|
|
112
|
+
this.platform.log.debug(data);
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Handle requests to get the current value of the "Current Heating Cooling State" characteristic
|
|
117
|
+
*/
|
|
118
|
+
handleCurrentHeatingCoolingStateGet() {
|
|
119
|
+
this.platform.log.debug('Triggered GET CurrentHeatingCoolingState');
|
|
120
|
+
return this._state.mode;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Handle requests to get the current value of the "Target Heating Cooling State" characteristic
|
|
124
|
+
*/
|
|
125
|
+
handleTargetHeatingCoolingStateGet() {
|
|
126
|
+
this.platform.log.debug('Triggered GET TargetHeatingCoolingState');
|
|
127
|
+
return this._state.mode;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Handle requests to set the "Target Heating Cooling State" characteristic
|
|
131
|
+
*/
|
|
132
|
+
handleTargetHeatingCoolingStateSet(value) {
|
|
133
|
+
this.platform.log.debug('Triggered SET TargetHeatingCoolingState:', value);
|
|
134
|
+
this._state.mode = value;
|
|
135
|
+
this._sendStateToAqara();
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Handle requests to get the current value of the "Current Temperature" characteristic
|
|
139
|
+
*/
|
|
140
|
+
handleCurrentTemperatureGet() {
|
|
141
|
+
this.platform.log.debug('Triggered GET CurrentTemperature');
|
|
142
|
+
return this._state.temperature;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Handle requests to get the current value of the "Target Temperature" characteristic
|
|
146
|
+
*/
|
|
147
|
+
handleTargetTemperatureGet() {
|
|
148
|
+
this.platform.log.debug('Triggered GET TargetTemperature');
|
|
149
|
+
return this._state.temperature;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Handle requests to set the "Target Temperature" characteristic
|
|
153
|
+
*/
|
|
154
|
+
handleTargetTemperatureSet(value) {
|
|
155
|
+
this.platform.log.debug('Triggered SET TargetTemperature:', value);
|
|
156
|
+
this._state.temperature = value;
|
|
157
|
+
this._sendStateToAqara();
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Handle requests to get the current value of the "Temperature Display Units" characteristic
|
|
161
|
+
*/
|
|
162
|
+
handleTemperatureDisplayUnitsGet() {
|
|
163
|
+
this.platform.log.debug('Triggered GET TemperatureDisplayUnits');
|
|
164
|
+
return this.Characteristic.TemperatureDisplayUnits.CELSIUS;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Handle requests to set the "Temperature Display Units" characteristic
|
|
168
|
+
*/
|
|
169
|
+
handleTemperatureDisplayUnitsSet(value) {
|
|
170
|
+
this.platform.log.debug('Triggered SET TemperatureDisplayUnits:', value);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
exports.IrACAccessory = IrACAccessory;
|
|
174
|
+
//# sourceMappingURL=IrACAccessory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IrACAccessory.js","sourceRoot":"","sources":["../../src/accessories/IrACAccessory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/accessories/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,iBAAiB,EAAC,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAC;AAE9C,OAAO,EACL,iBAAiB,EAEjB,aAAa,GACd,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.IrACAccessory = exports.AbstractAccessory = void 0;
|
|
4
|
+
const AbstractAccessory_1 = require("./AbstractAccessory");
|
|
5
|
+
Object.defineProperty(exports, "AbstractAccessory", { enumerable: true, get: function () { return AbstractAccessory_1.AbstractAccessory; } });
|
|
6
|
+
const IrACAccessory_1 = require("./IrACAccessory");
|
|
7
|
+
Object.defineProperty(exports, "IrACAccessory", { enumerable: true, get: function () { return IrACAccessory_1.IrACAccessory; } });
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/accessories/index.ts"],"names":[],"mappings":";;;AAAA,2DAAsD;AAIpD,kGAJM,qCAAiB,OAIN;AAHnB,mDAA8C;AAK5C,8FALM,6BAAa,OAKN"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
<link rel="stylesheet" href="main.css">
|
|
2
|
+
|
|
3
|
+
<div id="enter-code" class="form-group" style="display: none">
|
|
4
|
+
<label for="authCode">Authentication code</label>
|
|
5
|
+
<input type="text" class="form-control" id="authCode" aria-describedby="authCodeHelp">
|
|
6
|
+
<small id="authCodeHelp" class="form-text text-muted">Authentication code that you have received through email or
|
|
7
|
+
SMS</small>
|
|
8
|
+
<button id="authenticate" type="submit" class="btn btn-primary" onclick="authenticate(pluginConfig[0].username, document.getElementById('authCode').value)">
|
|
9
|
+
Authenticate
|
|
10
|
+
</button>
|
|
11
|
+
</div>
|
|
12
|
+
|
|
13
|
+
<div id="enter-home" class="form-group" style="display: none">
|
|
14
|
+
<label for="positionId">Authentication code</label>
|
|
15
|
+
<select class="form-control" id="positionId" aria-describedby="homeHelp">
|
|
16
|
+
</select>
|
|
17
|
+
<small id="homeHelp" class="form-text text-muted">Select your home to import IR AC controllers from</small>
|
|
18
|
+
<button id="selectHome" type="submit" class="btn btn-primary" onclick="saveHome()">
|
|
19
|
+
Confirm
|
|
20
|
+
</button>
|
|
21
|
+
</div>
|
|
22
|
+
|
|
23
|
+
<script type="text/javascript">
|
|
24
|
+
let schemaConfig = null;
|
|
25
|
+
let pluginConfig = [];
|
|
26
|
+
|
|
27
|
+
(async () => {
|
|
28
|
+
|
|
29
|
+
schemaConfig = await homebridge.getPluginConfigSchema();
|
|
30
|
+
pluginConfig = await homebridge.getPluginConfig();
|
|
31
|
+
|
|
32
|
+
const basicForm = homebridge.createForm(schemaConfig, pluginConfig[0], 'Proceed', 'Abort');
|
|
33
|
+
|
|
34
|
+
basicForm.onSubmit((formData) => {
|
|
35
|
+
updateConfig([formData]).then((configSave) => {
|
|
36
|
+
if(!configSave || !configSave[0].accessToken || configSave[0].accessToken.length === 0) {
|
|
37
|
+
getCode(configSave[0].username).then((code) => {
|
|
38
|
+
basicForm.end();
|
|
39
|
+
});
|
|
40
|
+
} else {
|
|
41
|
+
homebridge.toast.success('Settings successfully saved! Please restart Homebridge!');
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
})();
|
|
46
|
+
|
|
47
|
+
function getCode(username) {
|
|
48
|
+
return homebridge.request('/auth/init', {username}).then((result) => {
|
|
49
|
+
if(result && result.code === 0) {
|
|
50
|
+
document.getElementById("enter-code").style.display = 'block';
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return result;
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function authenticate(username, authCode) {
|
|
58
|
+
homebridge.request('/auth/login', {
|
|
59
|
+
username,
|
|
60
|
+
authCode
|
|
61
|
+
}).then((result) => {
|
|
62
|
+
if(result && result.code === 0) {
|
|
63
|
+
pluginConfig[0]['accessToken'] = result.result.accessToken;
|
|
64
|
+
pluginConfig[0]['refreshToken'] = result.result.refreshToken;
|
|
65
|
+
updateConfig(pluginConfig).then((result) => {
|
|
66
|
+
document.getElementById("enter-code").style.display = 'none';
|
|
67
|
+
selectHome();
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function reconfigureServer(config) {
|
|
74
|
+
return homebridge.request('/reconfigure', config);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function updateConfig(data) {
|
|
78
|
+
return homebridge.updatePluginConfig(data).then((savedConfig) => {
|
|
79
|
+
pluginConfig = savedConfig;
|
|
80
|
+
return reconfigureServer(savedConfig[0]).then((res) => {
|
|
81
|
+
if(res && res.code === 0) {
|
|
82
|
+
return savedConfig;
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function selectHome() {
|
|
89
|
+
homebridge.request('/aqara/homes', {}).then((result) => {
|
|
90
|
+
if(result && result.code === 0) {
|
|
91
|
+
if(result.result.data.length > 1) {
|
|
92
|
+
result.result.data.forEach((position) => {
|
|
93
|
+
document.getElementById('positionId').innerHTML += `<option value="${position.positionId}">${position.positionName}</option>`;
|
|
94
|
+
});
|
|
95
|
+
document.getElementById("enter-code").style.display = 'none';
|
|
96
|
+
document.getElementById("enter-home").style.display = 'block';
|
|
97
|
+
} else {
|
|
98
|
+
saveHome();
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function saveHome() {
|
|
105
|
+
pluginConfig[0]['positionId'] = document.getElementById('positionId').value;
|
|
106
|
+
updateConfig(pluginConfig).then((result) => {
|
|
107
|
+
document.getElementById("enter-home").style.display = 'none';
|
|
108
|
+
homebridge.toast.success('Successfully authenticated! Please save and restart Homebridge!');
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
</script>
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/ui/server.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
// your class MUST extend the HomebridgePluginUiServer
|
|
4
|
+
const plugin_ui_utils_1 = require("@homebridge/plugin-ui-utils");
|
|
5
|
+
const AqaraAPI_1 = require("../lib/AqaraAPI");
|
|
6
|
+
const fs_1 = require("fs");
|
|
7
|
+
class UiServer extends plugin_ui_utils_1.HomebridgePluginUiServer {
|
|
8
|
+
constructor() {
|
|
9
|
+
super();
|
|
10
|
+
this._aqara = null;
|
|
11
|
+
this._fillConfig();
|
|
12
|
+
this._initAqara();
|
|
13
|
+
this.onRequest('/auth/init', this.authInit.bind(this));
|
|
14
|
+
this.onRequest('/auth/login', this.getTokens.bind(this));
|
|
15
|
+
this.onRequest('/reconfigure', this.reconfigure.bind(this));
|
|
16
|
+
this.onRequest('/aqara/homes', this.getHomes.bind(this));
|
|
17
|
+
this.ready();
|
|
18
|
+
}
|
|
19
|
+
_initAqara(forceRecreate = false) {
|
|
20
|
+
if (this._config) {
|
|
21
|
+
this._aqara = AqaraAPI_1.AqaraAPI.factory({
|
|
22
|
+
region: this._config.region,
|
|
23
|
+
lang: this._config.lang,
|
|
24
|
+
appId: this._config.appId,
|
|
25
|
+
keyId: this._config.keyId,
|
|
26
|
+
appKey: this._config.appKey,
|
|
27
|
+
version: this._config.version,
|
|
28
|
+
}, forceRecreate);
|
|
29
|
+
this._aqara.accessToken = this._config.accessToken;
|
|
30
|
+
this._aqara.refreshToken = this._config.refreshToken;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
_fillConfig(config = null) {
|
|
34
|
+
if (config) {
|
|
35
|
+
this._config = config;
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
const readConfig = JSON.parse((0, fs_1.readFileSync)(this.homebridgeConfigPath, 'utf8'));
|
|
39
|
+
readConfig.platforms.forEach(platform => {
|
|
40
|
+
if (platform.platform === 'AqaraIrController') {
|
|
41
|
+
this._config = platform;
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Example only.
|
|
48
|
+
* Handle requests made from the UI to the `/hello` endpoint.
|
|
49
|
+
*/
|
|
50
|
+
async authInit({ username }) {
|
|
51
|
+
if (this._aqara) {
|
|
52
|
+
return this._aqara.getAuthCode(username)
|
|
53
|
+
.then(data => {
|
|
54
|
+
if (data.code === 0) {
|
|
55
|
+
return {
|
|
56
|
+
code: 0,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
throw new Error('Authentication failed');
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async getTokens({ username, authCode }) {
|
|
64
|
+
if (this._aqara) {
|
|
65
|
+
return this._aqara.getToken(username, authCode);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
async reconfigure(config) {
|
|
69
|
+
try {
|
|
70
|
+
this._fillConfig(config);
|
|
71
|
+
this._initAqara(true);
|
|
72
|
+
return {
|
|
73
|
+
code: 0,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
return {
|
|
78
|
+
code: 1,
|
|
79
|
+
error: error.message,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
async getHomes() {
|
|
84
|
+
if (this._aqara) {
|
|
85
|
+
return this._aqara.call('query.position.info', {
|
|
86
|
+
pageSize: 50,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
(() => {
|
|
92
|
+
return new UiServer;
|
|
93
|
+
})();
|
|
94
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/ui/server.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AAKjC;;GAEG;8BACY,GAAG;AAAlB,kBAEE"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const settings_1 = require("./settings");
|
|
3
|
+
const platform_1 = require("./platform");
|
|
4
|
+
module.exports = (api) => {
|
|
5
|
+
api.registerPlatform(settings_1.PLUGIN_NAME, settings_1.PLATFORM_NAME, platform_1.AqaraIrControllerPlatform);
|
|
6
|
+
};
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,yCAAsD;AACtD,yCAAuD;AAKvD,iBAAS,CAAC,GAAQ,EAAE,EAAE;IACpB,GAAG,CAAC,gBAAgB,CAAC,sBAAW,EAAE,wBAAa,EAAE,oCAAyB,CAAC,CAAC;AAC9E,CAAC,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export declare enum Region {
|
|
2
|
+
cn = 0,
|
|
3
|
+
us = 1,
|
|
4
|
+
kr = 2,
|
|
5
|
+
ru = 3,
|
|
6
|
+
de = 4,
|
|
7
|
+
sg = 5
|
|
8
|
+
}
|
|
9
|
+
export declare enum Language {
|
|
10
|
+
en = "en",
|
|
11
|
+
zh = "zh"
|
|
12
|
+
}
|
|
13
|
+
export declare class Options {
|
|
14
|
+
region: Region;
|
|
15
|
+
version: string;
|
|
16
|
+
lang: Language;
|
|
17
|
+
appId: string;
|
|
18
|
+
keyId: string;
|
|
19
|
+
appKey: string;
|
|
20
|
+
constructor(region: Region, version: string, lang: Language, appId: string, keyId: string, appKey: string);
|
|
21
|
+
}
|
|
22
|
+
export declare class AqaraAPI {
|
|
23
|
+
private _options;
|
|
24
|
+
private _accessToken;
|
|
25
|
+
private _refreshToken;
|
|
26
|
+
private _client;
|
|
27
|
+
constructor(_options: Options);
|
|
28
|
+
get apiDomain(): "open-kr.aqara.com" | "open-ger.aqara.com" | "open-ru.aqara.com" | "open-sg.aqara.com" | "open-usa.aqara.com" | "open-cn.aqara.com";
|
|
29
|
+
get deviceSDKDomain(): "coap-kr.aqara.com" | "coap-ger.aqara.com" | "coap-ru.aqara.com" | "coap-sg.aqara.com" | "aiot-coap-usa.aqara.com" | "aiot-coap.aqara.cn";
|
|
30
|
+
get url(): string;
|
|
31
|
+
private _buildConfig;
|
|
32
|
+
private _buildData;
|
|
33
|
+
getAuthCode(account: string, accessTokenValidity?: string): Promise<any>;
|
|
34
|
+
getToken(account: string, authCode: string): Promise<any>;
|
|
35
|
+
call(intent: string, data: any): Promise<any>;
|
|
36
|
+
authenticate(account: string, accessTokenValidity?: string): Promise<{
|
|
37
|
+
accessToken: any;
|
|
38
|
+
refreshToken: any;
|
|
39
|
+
}>;
|
|
40
|
+
set accessToken(accessToken: string | undefined);
|
|
41
|
+
get accessToken(): string | undefined;
|
|
42
|
+
set refreshToken(refreshToken: string);
|
|
43
|
+
get options(): Options;
|
|
44
|
+
static factory(options: Options, forceRecreate?: boolean): AqaraAPI;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=AqaraAPI.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AqaraAPI.d.ts","sourceRoot":"","sources":["../../src/lib/AqaraAPI.ts"],"names":[],"mappings":"AAKA,oBAAY,MAAM;IAChB,EAAE,IAAA;IACF,EAAE,IAAA;IACF,EAAE,IAAA;IACF,EAAE,IAAA;IACF,EAAE,IAAA;IACF,EAAE,IAAA;CACH;AAED,oBAAY,QAAQ;IAClB,EAAE,OAAO;IACT,EAAE,OAAO;CACV;AAED,qBAAa,OAAO;IAET,MAAM,EAAE,MAAM;IACd,OAAO,EAAE,MAAM;IACf,IAAI,EAAE,QAAQ;IACd,KAAK,EAAE,MAAM;IACb,KAAK,EAAE,MAAM;IACb,MAAM,EAAE,MAAM;gBALd,MAAM,EAAE,MAAkB,EAC1B,OAAO,EAAE,MAAe,EACxB,IAAI,EAAE,QAAsB,EAC5B,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM;CAGxB;AAmCD,qBAAa,QAAQ;IAOP,OAAO,CAAC,QAAQ;IAL5B,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,aAAa,CAAqB;IAE1C,OAAO,CAAC,OAAO,CAAgB;gBAEX,QAAQ,EAAE,OAAO;IAMrC,IAAW,SAAS,wIAenB;IAED,IAAW,eAAe,8IAezB;IAED,IAAI,GAAG,WAEN;IAED,OAAO,CAAC,YAAY;IAgCpB,OAAO,CAAC,UAAU;IAOX,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,mBAAmB,SAAQ;IAQxD,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;IAQ1C,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG;IAU9B,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,mBAAmB,SAAQ;;;;IAwBhE,IAAI,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,EAE9C;IAED,IAAI,WAAW,IAAI,MAAM,GAAG,SAAS,CAEpC;IAED,IAAI,YAAY,CAAC,YAAY,EAAE,MAAM,EAEpC;IAED,IAAI,OAAO,IAAI,OAAO,CAErB;WAEa,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,aAAa,UAAQ;CAO9D"}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.AqaraAPI = exports.Options = exports.Language = exports.Region = void 0;
|
|
30
|
+
const crypto = __importStar(require("crypto"));
|
|
31
|
+
const axios_1 = __importDefault(require("axios"));
|
|
32
|
+
const help_1 = require("./help");
|
|
33
|
+
var Region;
|
|
34
|
+
(function (Region) {
|
|
35
|
+
Region[Region["cn"] = 0] = "cn";
|
|
36
|
+
Region[Region["us"] = 1] = "us";
|
|
37
|
+
Region[Region["kr"] = 2] = "kr";
|
|
38
|
+
Region[Region["ru"] = 3] = "ru";
|
|
39
|
+
Region[Region["de"] = 4] = "de";
|
|
40
|
+
Region[Region["sg"] = 5] = "sg";
|
|
41
|
+
})(Region = exports.Region || (exports.Region = {}));
|
|
42
|
+
var Language;
|
|
43
|
+
(function (Language) {
|
|
44
|
+
Language["en"] = "en";
|
|
45
|
+
Language["zh"] = "zh";
|
|
46
|
+
})(Language = exports.Language || (exports.Language = {}));
|
|
47
|
+
class Options {
|
|
48
|
+
constructor(region = Region.cn, version = 'v3.0', lang = Language.en, appId, keyId, appKey) {
|
|
49
|
+
this.region = region;
|
|
50
|
+
this.version = version;
|
|
51
|
+
this.lang = lang;
|
|
52
|
+
this.appId = appId;
|
|
53
|
+
this.keyId = keyId;
|
|
54
|
+
this.appKey = appKey;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
exports.Options = Options;
|
|
58
|
+
/**
|
|
59
|
+
* Generate a sign value based on the inputs.
|
|
60
|
+
* @param {string} accessToken - The access token.
|
|
61
|
+
* @param {string} appId - The app ID.
|
|
62
|
+
* @param {string} keyId - The key ID.
|
|
63
|
+
* @param {string} nonce - A random nonce string.
|
|
64
|
+
* @param {string} time - The timestamp.
|
|
65
|
+
* @param {string} appKey - The app key.
|
|
66
|
+
* @returns {string} The generated sign value or null in case of an error.
|
|
67
|
+
*/
|
|
68
|
+
function createSign(appId, keyId, nonce, time, appKey, accessToken) {
|
|
69
|
+
let sb = '';
|
|
70
|
+
if (accessToken && accessToken.trim() !== '') {
|
|
71
|
+
sb += `Accesstoken=${accessToken}&`;
|
|
72
|
+
}
|
|
73
|
+
sb += `Appid=${appId}&Keyid=${keyId}&Nonce=${nonce}&Time=${time}${appKey}`;
|
|
74
|
+
const signStr = sb.toLowerCase();
|
|
75
|
+
return md5(signStr);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Generate the MD5 hash of a string.
|
|
79
|
+
* @param {string} sourceStr - The input string.
|
|
80
|
+
* @returns {string} The MD5 hash in hexadecimal format.
|
|
81
|
+
*/
|
|
82
|
+
function md5(sourceStr) {
|
|
83
|
+
return crypto.createHash('md5').update(sourceStr, 'utf-8').digest('hex');
|
|
84
|
+
}
|
|
85
|
+
let instance;
|
|
86
|
+
class AqaraAPI {
|
|
87
|
+
constructor(_options) {
|
|
88
|
+
this._options = _options;
|
|
89
|
+
this._client = axios_1.default.create({
|
|
90
|
+
baseURL: this.url,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
get apiDomain() {
|
|
94
|
+
switch (this._options.region) {
|
|
95
|
+
case Region.kr:
|
|
96
|
+
return 'open-kr.aqara.com';
|
|
97
|
+
case Region.de:
|
|
98
|
+
return 'open-ger.aqara.com';
|
|
99
|
+
case Region.ru:
|
|
100
|
+
return 'open-ru.aqara.com';
|
|
101
|
+
case Region.sg:
|
|
102
|
+
return 'open-sg.aqara.com';
|
|
103
|
+
case Region.us:
|
|
104
|
+
return 'open-usa.aqara.com';
|
|
105
|
+
default:
|
|
106
|
+
return 'open-cn.aqara.com';
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
get deviceSDKDomain() {
|
|
110
|
+
switch (this._options.region) {
|
|
111
|
+
case Region.kr:
|
|
112
|
+
return 'coap-kr.aqara.com';
|
|
113
|
+
case Region.de:
|
|
114
|
+
return 'coap-ger.aqara.com';
|
|
115
|
+
case Region.ru:
|
|
116
|
+
return 'coap-ru.aqara.com';
|
|
117
|
+
case Region.sg:
|
|
118
|
+
return 'coap-sg.aqara.com';
|
|
119
|
+
case Region.us:
|
|
120
|
+
return 'aiot-coap-usa.aqara.com';
|
|
121
|
+
default:
|
|
122
|
+
return 'aiot-coap.aqara.cn';
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
get url() {
|
|
126
|
+
return `https://${this.apiDomain}/${this._options.version}/open/api`;
|
|
127
|
+
}
|
|
128
|
+
_buildConfig() {
|
|
129
|
+
const nonce = crypto.randomUUID();
|
|
130
|
+
const time = Date.now().toString();
|
|
131
|
+
const headers = {
|
|
132
|
+
'Appid': this._options.appId,
|
|
133
|
+
'Keyid': this._options.keyId,
|
|
134
|
+
'Nonce': nonce,
|
|
135
|
+
'Sign': createSign(this._options.appId, this._options.keyId, nonce, time, this._options.appKey, this._accessToken),
|
|
136
|
+
'Lang': this._options.lang,
|
|
137
|
+
'Time': time,
|
|
138
|
+
};
|
|
139
|
+
if (this._accessToken) {
|
|
140
|
+
headers['Accesstoken'] = this._accessToken;
|
|
141
|
+
}
|
|
142
|
+
const config = {
|
|
143
|
+
headers,
|
|
144
|
+
};
|
|
145
|
+
return config;
|
|
146
|
+
}
|
|
147
|
+
_buildData(intent, data) {
|
|
148
|
+
return {
|
|
149
|
+
intent,
|
|
150
|
+
data,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
getAuthCode(account, accessTokenValidity = '10y') {
|
|
154
|
+
return this.call('config.auth.getAuthCode', {
|
|
155
|
+
account,
|
|
156
|
+
accountType: 0,
|
|
157
|
+
accessTokenValidity,
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
getToken(account, authCode) {
|
|
161
|
+
return this.call('config.auth.getToken', {
|
|
162
|
+
account,
|
|
163
|
+
accountType: 0,
|
|
164
|
+
authCode,
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
call(intent, data) {
|
|
168
|
+
return this._client.post('', this._buildData(intent, data), this._buildConfig()).then((res) => {
|
|
169
|
+
if (res.data.code === 0) {
|
|
170
|
+
return res.data;
|
|
171
|
+
}
|
|
172
|
+
throw new Error(JSON.stringify(res.data));
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
authenticate(account, accessTokenValidity = '10y') {
|
|
176
|
+
return this.getAuthCode(account, accessTokenValidity)
|
|
177
|
+
.then(res => {
|
|
178
|
+
return (0, help_1.askQuestion)('Enter Aqara authentication code: ');
|
|
179
|
+
}, (e) => {
|
|
180
|
+
throw new Error('Authentication failed: ' + e.message);
|
|
181
|
+
})
|
|
182
|
+
.then(authCode => {
|
|
183
|
+
return this.getToken(account, authCode);
|
|
184
|
+
})
|
|
185
|
+
.then(data => {
|
|
186
|
+
this._accessToken = data.result.accessToken;
|
|
187
|
+
this._refreshToken = data.result.refreshToken;
|
|
188
|
+
return {
|
|
189
|
+
accessToken: data.result.accessToken,
|
|
190
|
+
refreshToken: data.result.refreshToken,
|
|
191
|
+
};
|
|
192
|
+
}, (e) => {
|
|
193
|
+
throw new Error('Authentication failed: ' + e.message);
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
set accessToken(accessToken) {
|
|
197
|
+
this._accessToken = accessToken;
|
|
198
|
+
}
|
|
199
|
+
get accessToken() {
|
|
200
|
+
return this._accessToken;
|
|
201
|
+
}
|
|
202
|
+
set refreshToken(refreshToken) {
|
|
203
|
+
this._refreshToken = refreshToken;
|
|
204
|
+
}
|
|
205
|
+
get options() {
|
|
206
|
+
return this._options;
|
|
207
|
+
}
|
|
208
|
+
static factory(options, forceRecreate = false) {
|
|
209
|
+
if (instance && !forceRecreate) {
|
|
210
|
+
return instance;
|
|
211
|
+
}
|
|
212
|
+
return instance = new AqaraAPI(options);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
exports.AqaraAPI = AqaraAPI;
|
|
216
|
+
//# sourceMappingURL=AqaraAPI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AqaraAPI.js","sourceRoot":"","sources":["../../src/lib/AqaraAPI.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../../src/lib/help.ts"],"names":[],"mappings":"AAOA,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAM7D"}
|
package/dist/lib/help.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.askQuestion = void 0;
|
|
7
|
+
const node_readline_1 = __importDefault(require("node:readline"));
|
|
8
|
+
const rl = node_readline_1.default.createInterface({
|
|
9
|
+
input: process.stdin,
|
|
10
|
+
output: process.stdout,
|
|
11
|
+
});
|
|
12
|
+
function askQuestion(question) {
|
|
13
|
+
return new Promise((resolve) => {
|
|
14
|
+
rl.question(question, (answer) => {
|
|
15
|
+
resolve(answer);
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
exports.askQuestion = askQuestion;
|
|
20
|
+
//# sourceMappingURL=help.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"help.js","sourceRoot":"","sources":["../../src/lib/help.ts"],"names":[],"mappings":";;;;;;AAAA,kEAAqC;AAErC,MAAM,EAAE,GAAG,uBAAQ,CAAC,eAAe,CAAC;IAClC,KAAK,EAAG,OAAO,CAAC,KAAK;IACrB,MAAM,EAAE,OAAO,CAAC,MAAM;CACvB,CAAC,CAAC;AAEH,SAAgB,WAAW,CAAC,QAAgB;IAC1C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,EAAE;YAC/B,OAAO,CAAC,MAAM,CAAC,CAAC;QAClB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAND,kCAMC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { API, Categories, DynamicPlatformPlugin, Logging, PlatformAccessory, PlatformConfig, UnknownContext } from 'homebridge';
|
|
2
|
+
import { AqaraAPI } from './lib/AqaraAPI';
|
|
3
|
+
export declare class AqaraIrControllerPlatform implements DynamicPlatformPlugin {
|
|
4
|
+
readonly log: Logging;
|
|
5
|
+
readonly config: PlatformConfig;
|
|
6
|
+
readonly api: API;
|
|
7
|
+
private _accessories;
|
|
8
|
+
private _aqara;
|
|
9
|
+
constructor(log: Logging, config: PlatformConfig, api: API);
|
|
10
|
+
get aqara(): AqaraAPI;
|
|
11
|
+
discoverDevices(): void;
|
|
12
|
+
configureAccessory(accessory: PlatformAccessory): void;
|
|
13
|
+
addAccessory(name: string, category: Categories, config: UnknownContext): void;
|
|
14
|
+
removeAccessories(uuids?: string[]): void;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=platform.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../src/platform.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,GAAG,EAEH,UAAU,EACV,qBAAqB,EACrB,OAAO,EACP,iBAAiB,EAEjB,cAAc,EACd,cAAc,EACf,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAC,QAAQ,EAAC,MAAM,gBAAgB,CAAC;AAExC,qBAAa,yBAA0B,YAAW,qBAAqB;aAOnD,GAAG,EAAE,OAAO;aACZ,MAAM,EAAE,cAAc;aACtB,GAAG,EAAE,GAAG;IAP1B,OAAO,CAAC,YAAY,CAA4C;IAEhE,OAAO,CAAC,MAAM,CAAW;gBAGP,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,cAAc,EACtB,GAAG,EAAE,GAAG;IAsB1B,IAAW,KAAK,IAAI,QAAQ,CAE3B;IAED,eAAe;IA4Cf,kBAAkB,CAAC,SAAS,EAAE,iBAAiB,GAAG,IAAI;IActD,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,cAAc;IAkBvE,iBAAiB,CAAC,KAAK,GAAE,MAAM,EAAO;CAevC"}
|
package/dist/platform.js
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AqaraIrControllerPlatform = void 0;
|
|
4
|
+
const settings_1 = require("./settings");
|
|
5
|
+
const accessories_1 = require("./accessories");
|
|
6
|
+
const AqaraAPI_1 = require("./lib/AqaraAPI");
|
|
7
|
+
class AqaraIrControllerPlatform {
|
|
8
|
+
constructor(log, config, api) {
|
|
9
|
+
this.log = log;
|
|
10
|
+
this.config = config;
|
|
11
|
+
this.api = api;
|
|
12
|
+
this._accessories = {};
|
|
13
|
+
this._aqara = AqaraAPI_1.AqaraAPI.factory({
|
|
14
|
+
region: config.region,
|
|
15
|
+
lang: config.lang,
|
|
16
|
+
appId: config.appId,
|
|
17
|
+
keyId: config.keyId,
|
|
18
|
+
appKey: config.appKey,
|
|
19
|
+
version: config.version,
|
|
20
|
+
});
|
|
21
|
+
this._aqara.accessToken = config.accessToken && config.accessToken.length ? config.accessToken : undefined;
|
|
22
|
+
this._aqara.refreshToken = config.refreshToken && config.refreshToken.length ? config.refreshToken : undefined;
|
|
23
|
+
this.api.on("didFinishLaunching" /* APIEvent.DID_FINISH_LAUNCHING */, () => {
|
|
24
|
+
this.log.debug('Executed didFinishLaunching callback');
|
|
25
|
+
this.discoverDevices();
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
get aqara() {
|
|
29
|
+
return this._aqara;
|
|
30
|
+
}
|
|
31
|
+
discoverDevices() {
|
|
32
|
+
const irAC = [];
|
|
33
|
+
if (this.aqara.accessToken) {
|
|
34
|
+
const filter = {};
|
|
35
|
+
if (this.config && this.config.positionId && this.config.positionId.length) {
|
|
36
|
+
filter['positionId'] = this.config.positionId;
|
|
37
|
+
}
|
|
38
|
+
this._aqara.call('query.device.info', filter)
|
|
39
|
+
.then(data => {
|
|
40
|
+
data.result.data.forEach((device) => {
|
|
41
|
+
if (device.model === 'virtual.ir.ac') {
|
|
42
|
+
irAC.push(device);
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
}, (err) => {
|
|
46
|
+
this.log.debug(err.message);
|
|
47
|
+
})
|
|
48
|
+
.then(() => {
|
|
49
|
+
const promises = [];
|
|
50
|
+
irAC.forEach((device) => {
|
|
51
|
+
promises.push(this._aqara.call('query.ir.info', {
|
|
52
|
+
did: device.did,
|
|
53
|
+
}).then(data => {
|
|
54
|
+
device['info'] = data.result;
|
|
55
|
+
}));
|
|
56
|
+
promises.push(this._aqara.call('query.ir.acState', {
|
|
57
|
+
did: device.did,
|
|
58
|
+
}).then(data => {
|
|
59
|
+
device['state'] = data.result;
|
|
60
|
+
}));
|
|
61
|
+
});
|
|
62
|
+
return Promise.all(promises);
|
|
63
|
+
})
|
|
64
|
+
.then((data) => {
|
|
65
|
+
irAC.forEach((device) => {
|
|
66
|
+
this.addAccessory(device.deviceName, 21 /* Categories.AIR_CONDITIONER */, device);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
configureAccessory(accessory) {
|
|
72
|
+
this.log('Configuring accessory %s', accessory.displayName);
|
|
73
|
+
accessory.on("identify" /* PlatformAccessoryEvent.IDENTIFY */, () => {
|
|
74
|
+
this.log('%s identified!', accessory.displayName);
|
|
75
|
+
});
|
|
76
|
+
if (accessory.category === 21 /* this.api.hap.Categories.AIR_CONDITIONER */) {
|
|
77
|
+
new accessories_1.IrACAccessory(this, accessory, accessory.context);
|
|
78
|
+
}
|
|
79
|
+
this._accessories[accessory.UUID] = accessory;
|
|
80
|
+
}
|
|
81
|
+
addAccessory(name, category, config) {
|
|
82
|
+
const uuid = this.api.hap.uuid.generate(name);
|
|
83
|
+
if (!this._accessories[uuid]) {
|
|
84
|
+
this.log.info('Adding new accessory with name %s', name);
|
|
85
|
+
const accessory = new this.api.platformAccessory(name, uuid, category);
|
|
86
|
+
accessory.context = config;
|
|
87
|
+
this.configureAccessory(accessory); // abusing the configureAccessory here
|
|
88
|
+
this.api.registerPlatformAccessories(settings_1.PLUGIN_NAME, settings_1.PLATFORM_NAME, [accessory]);
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
this.log.info('Skipping to add new accessory with name %s because it exists in cache', name);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
removeAccessories(uuids = []) {
|
|
95
|
+
const found = [];
|
|
96
|
+
uuids.forEach((uuid) => {
|
|
97
|
+
if (this._accessories[uuid]) {
|
|
98
|
+
found.push(this._accessories[uuid]);
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
this.api.unregisterPlatformAccessories(settings_1.PLUGIN_NAME, settings_1.PLATFORM_NAME, found);
|
|
102
|
+
found.forEach((accessory) => {
|
|
103
|
+
delete this._accessories[accessory.UUID];
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
exports.AqaraIrControllerPlatform = AqaraIrControllerPlatform;
|
|
108
|
+
//# sourceMappingURL=platform.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform.js","sourceRoot":"","sources":["../src/platform.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This is the name of the platform that users will use to register the plugin in the Homebridge config.json
|
|
3
|
+
*/
|
|
4
|
+
export declare const PLATFORM_NAME = "AqaraIrController";
|
|
5
|
+
/**
|
|
6
|
+
* This must match the name of your plugin as defined the package.json
|
|
7
|
+
*/
|
|
8
|
+
export declare const PLUGIN_NAME = "homebridge-aqara-ir-controller";
|
|
9
|
+
//# sourceMappingURL=settings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,aAAa,sBAAsB,CAAC;AAEjD;;GAEG;AACH,eAAO,MAAM,WAAW,mCAAmC,CAAC"}
|
package/dist/settings.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PLUGIN_NAME = exports.PLATFORM_NAME = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* This is the name of the platform that users will use to register the plugin in the Homebridge config.json
|
|
6
|
+
*/
|
|
7
|
+
exports.PLATFORM_NAME = 'AqaraIrController';
|
|
8
|
+
/**
|
|
9
|
+
* This must match the name of your plugin as defined the package.json
|
|
10
|
+
*/
|
|
11
|
+
exports.PLUGIN_NAME = 'homebridge-aqara-ir-controller';
|
|
12
|
+
//# sourceMappingURL=settings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":";;;AAAA;;GAEG;AACU,QAAA,aAAa,GAAG,mBAAmB,CAAC;AAEjD;;GAEG;AACU,QAAA,WAAW,GAAG,gCAAgC,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"displayName": "Homebridge Aqara IR Controller",
|
|
3
|
+
"name": "homebridge-aqara-ir-controller",
|
|
4
|
+
"version": "1.0.1",
|
|
5
|
+
"description": "A simple plugin that exposes Aqara Ir AC control as a Thermostat",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"homepage": "https://github.com/Vaxter/Homebridge-Aqara-IR-Controller",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/Vaxter/Homebridge-Aqara-IR-Controller.git"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/Vaxter/Homebridge-Aqara-IR-Controller/issues"
|
|
14
|
+
},
|
|
15
|
+
"author": "vaxter",
|
|
16
|
+
"engines": {
|
|
17
|
+
"node": "^22.12.0",
|
|
18
|
+
"homebridge": "^1.8.0"
|
|
19
|
+
},
|
|
20
|
+
"main": "dist/index.js",
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "rimraf ./dist && tsc && mv ./dist/ui ./dist/homebridge-ui && mkdir ./dist/homebridge-ui/public && cp -r ./src/ui/public/* ./dist/homebridge-ui/public/",
|
|
23
|
+
"lint": "eslint . --max-warnings=0",
|
|
24
|
+
"watch": "npm run build && npm link && nodemon"
|
|
25
|
+
},
|
|
26
|
+
"keywords": [
|
|
27
|
+
"homebridge-plugin"
|
|
28
|
+
],
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@homebridge/plugin-ui-utils": "^2.0.0",
|
|
31
|
+
"axios": "^1.7.9"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@types/node": "^18.16.20",
|
|
35
|
+
"@typescript-eslint/eslint-plugin": "^5.62.0",
|
|
36
|
+
"@typescript-eslint/parser": "^5.62.0",
|
|
37
|
+
"eslint": "^8.45.0",
|
|
38
|
+
"homebridge": "^1.8.5",
|
|
39
|
+
"homebridge-config-ui-x": "^4.64.0",
|
|
40
|
+
"nodemon": "^2.0.22",
|
|
41
|
+
"rimraf": "^3.0.2",
|
|
42
|
+
"ts-node": "^10.9.1",
|
|
43
|
+
"typescript": "^4.9.5"
|
|
44
|
+
}
|
|
45
|
+
}
|