homebridge-plejd 1.1.3-beta.0

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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 Alexander Herlin
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,38 @@
1
+
2
+ <SPAN ALIGN="CENTER" STYLE="text-align:center">
3
+ <DIV ALIGN="CENTER" STYLE="text-align:center">
4
+
5
+ # [Plejd](https://www.plejd.com)
6
+
7
+ ## HomeKit support for the Plejd BLE platform using [Homebridge](https://homebridge.io)
8
+ </DIV>
9
+ </SPAN>
10
+
11
+
12
+ ---
13
+ <br />
14
+
15
+ ### Dependencies needed for Raspberry PI
16
+ This is tested on a raspberry pi 3b+ using DIM-02 and DIM-01. Please let me know if there's any issues with other units. Feel free to poke around.
17
+
18
+ ```bash
19
+ sudo apt-get install bluetooth bluez libbluetooth-dev libudev-dev
20
+ ```
21
+
22
+ Check out ble lib [@abandonware/Noble](https://github.com/abandonware/noble) for you specific platform
23
+
24
+ ----
25
+ <br/>
26
+
27
+ ## TODO: Extract crypto key
28
+
29
+ For now look for guides online. Backup your phone unencrypted. Download an extractor and look for a .site file within plejd.
30
+
31
+ ```com.plejd.consumer.light ... .site .... .PlejdMesh.CryptoKey ```
32
+
33
+ ----
34
+ <br />
35
+
36
+ ## Thanks
37
+
38
+ Big thanks to [@blommegard](https://github.com/blommegard) (https://github.com/blommegard/homebridge-plejd) for the base of this repo
@@ -0,0 +1,52 @@
1
+ {
2
+ "pluginAlias": "Plejd",
3
+ "pluginType": "platform",
4
+ "headerDisplay": "Add your crypto key & your Plejd devices",
5
+ "footerDisplay": "Tip: Plejd app -> Settings -> Devices -> Click on device -> About device",
6
+ "singular": true,
7
+ "schema": {
8
+ "crypto_key": {
9
+ "title": "Crypto key",
10
+ "type": "string",
11
+ "required": true,
12
+ "placeholder": "828291.. or 82-82-91...",
13
+ "description": "With or without '-' "
14
+ },
15
+ "devices": {
16
+ "type": "array",
17
+ "items": {
18
+ "title": "Device",
19
+ "type": "object",
20
+ "properties": {
21
+ "name": {
22
+ "title": "Name",
23
+ "type": "string",
24
+ "placeholder": "Kitchen table",
25
+ "required": true
26
+ },
27
+ "model": {
28
+ "title": "Model",
29
+ "type": "string",
30
+ "enum": [
31
+ "CTR-01",
32
+ "DAL-01",
33
+ "DIM-01",
34
+ "DIM-02",
35
+ "LED-10",
36
+ "REL-01-2P",
37
+ "REL-02",
38
+ "SPR-01"
39
+ ],
40
+ "required": true
41
+ },
42
+ "identifier": {
43
+ "title": "Identifier",
44
+ "type": "integer",
45
+ "placeholder": "11",
46
+ "required": true
47
+ }
48
+ }
49
+ }
50
+ }
51
+ }
52
+ }
@@ -0,0 +1,7 @@
1
+ import { API } from 'homebridge';
2
+ declare const _default: (api: API) => void;
3
+ /**
4
+ * This method registers the platform with Homebridge
5
+ */
6
+ export = _default;
7
+ //# sourceMappingURL=index.d.ts.map
@@ -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;8BAQlB,GAAG;AAHlB;;GAEG;AACH,kBAEE"}
package/dist/index.js ADDED
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ const settings_1 = require("./settings");
3
+ const plejdPlatform_1 = require("./plejdPlatform");
4
+ module.exports = (api) => {
5
+ api.registerPlatform(settings_1.PLUGIN_NAME, settings_1.PLATFORM_NAME, plejdPlatform_1.PlejdPlatform);
6
+ };
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,yCAAwD;AACxD,mDAAgD;AAKhD,iBAAS,CAAC,GAAQ,EAAE,EAAE;IACpB,GAAG,CAAC,gBAAgB,CAAC,sBAAW,EAAE,wBAAa,EAAE,6BAAa,CAAC,CAAC;AAClE,CAAC,CAAC"}
@@ -0,0 +1,13 @@
1
+ /// <reference types="node" />
2
+ export interface Device {
3
+ name: string;
4
+ model: string;
5
+ identifier: number;
6
+ isDimmer: boolean;
7
+ uuid: string;
8
+ }
9
+ export interface UserInputConfig {
10
+ devices: Device[];
11
+ cryptoKey: Buffer;
12
+ }
13
+ //# sourceMappingURL=model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":";AAAA,MAAM,WAAW,MAAM;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,eAAe;IAC5B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACrB"}
package/dist/model.js ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.js","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":""}
@@ -0,0 +1,28 @@
1
+ import { API, DynamicPlatformPlugin, Logger, PlatformAccessory, PlatformConfig, Service, Characteristic } from 'homebridge';
2
+ import { UserInputConfig } from './model';
3
+ import { PlejdService } from './plejdService';
4
+ export declare class PlejdPlatform implements DynamicPlatformPlugin {
5
+ readonly log: Logger;
6
+ readonly config: PlatformConfig;
7
+ readonly api: API;
8
+ readonly Service: typeof Service;
9
+ readonly Characteristic: typeof Characteristic;
10
+ readonly userInputConfig: UserInputConfig;
11
+ readonly plejdService: PlejdService;
12
+ readonly accessories: PlatformAccessory[];
13
+ constructor(log: Logger, config: PlatformConfig, api: API);
14
+ /**
15
+ * This function is invoked when homebridge restores cached accessories from disk at startup.
16
+ * It should be used to setup event handlers for characteristics and update respective values.
17
+ */
18
+ configureAccessory(accessory: PlatformAccessory): void;
19
+ /**
20
+ * This is an example method showing how to register discovered accessories.
21
+ * Accessories must only be registered once, previously created accessories
22
+ * must not be registered again to prevent "duplicate UUID" errors.
23
+ */
24
+ discoverDevices(): void;
25
+ onPlejdUpdates(identifier: number, state: number, dim?: number): void;
26
+ private generateId;
27
+ }
28
+ //# sourceMappingURL=plejdPlatform.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plejdPlatform.d.ts","sourceRoot":"","sources":["../src/plejdPlatform.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,qBAAqB,EAAE,MAAM,EAAE,iBAAiB,EAAE,cAAc,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAI5H,OAAO,EAAU,eAAe,EAAE,MAAM,SAAS,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,qBAAa,aAAc,YAAW,qBAAqB;aAWvC,GAAG,EAAE,MAAM;aACX,MAAM,EAAE,cAAc;aACtB,GAAG,EAAE,GAAG;IAZ1B,SAAgB,OAAO,EAAE,OAAO,OAAO,CAAwB;IAC/D,SAAgB,cAAc,EAAE,OAAO,cAAc,CAA+B;IACpF,SAAgB,eAAe,EAAG,eAAe,CAAC;IAElD,SAAgB,YAAY,EAAE,YAAY,CAAC;IAG3C,SAAgB,WAAW,EAAE,iBAAiB,EAAE,CAAM;gBAGpC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,cAAc,EACtB,GAAG,EAAE,GAAG;IAuB1B;;;KAGC;IACD,kBAAkB,CAAC,SAAS,EAAE,iBAAiB;IAK/C;;;;KAIC;IACD,eAAe;IAiCf,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM;IAuB9D,OAAO,CAAC,UAAU;CAGnB"}
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PlejdPlatform = void 0;
4
+ const settings_1 = require("./settings");
5
+ const plejdPlatformAccessory_1 = require("./plejdPlatformAccessory");
6
+ const plejdService_1 = require("./plejdService");
7
+ class PlejdPlatform {
8
+ constructor(log, config, api) {
9
+ this.log = log;
10
+ this.config = config;
11
+ this.api = api;
12
+ this.Service = this.api.hap.Service;
13
+ this.Characteristic = this.api.hap.Characteristic;
14
+ // this is used to track restored cached accessories
15
+ this.accessories = [];
16
+ this.log.debug('Finished initializing platform:', this.config.platform);
17
+ // Update this to have it computed.
18
+ const devs = config['devices'];
19
+ for (let i = 0; i < devs.length; i++) {
20
+ devs[i].isDimmer = settings_1.PLEJD_LIGHTS.includes((devs[i].model));
21
+ devs[i].uuid = this.generateId(devs[i].identifier.toString());
22
+ }
23
+ const cryptoKey = Buffer.from(config['crypto_key'].replace(/-/g, ''), 'hex');
24
+ this.userInputConfig = {
25
+ devices: devs,
26
+ cryptoKey: cryptoKey,
27
+ };
28
+ this.log.debug('UserConfig: ', this.userInputConfig);
29
+ this.plejdService = new plejdService_1.PlejdService(this.userInputConfig, log, this.onPlejdUpdates.bind(this));
30
+ this.api.on('didFinishLaunching', () => {
31
+ this.discoverDevices();
32
+ });
33
+ }
34
+ /**
35
+ * This function is invoked when homebridge restores cached accessories from disk at startup.
36
+ * It should be used to setup event handlers for characteristics and update respective values.
37
+ */
38
+ configureAccessory(accessory) {
39
+ this.log.info('Loading accessory from cache:', accessory.displayName);
40
+ this.accessories.push(accessory);
41
+ }
42
+ /**
43
+ * This is an example method showing how to register discovered accessories.
44
+ * Accessories must only be registered once, previously created accessories
45
+ * must not be registered again to prevent "duplicate UUID" errors.
46
+ */
47
+ discoverDevices() {
48
+ const units = this.userInputConfig.devices.map(x => x.uuid);
49
+ const notRegistered = this.accessories.filter(ac => !units.includes(ac.UUID));
50
+ if (notRegistered.length > 0) {
51
+ this.api.unregisterPlatformAccessories(settings_1.PLUGIN_NAME, settings_1.PLATFORM_NAME, notRegistered);
52
+ }
53
+ for (const device of this.userInputConfig.devices) {
54
+ const existingAccessory = this.accessories.find(accessory => accessory.UUID === device.uuid);
55
+ if (existingAccessory) {
56
+ this.log.info('Restoring existing accessory from cache:', existingAccessory.displayName);
57
+ existingAccessory.context.device = device;
58
+ existingAccessory.displayName = device.name;
59
+ this.api.updatePlatformAccessories([existingAccessory]);
60
+ // Create a handle for the device to take care of logic
61
+ // lives for as long as "this" is active.
62
+ new plejdPlatformAccessory_1.PlejdPlatformAccessory(this, existingAccessory);
63
+ }
64
+ else {
65
+ this.log.info('Adding new accessory:', device.name);
66
+ const accessory = new this.api.platformAccessory(device.name, device.uuid);
67
+ accessory.context.device = device;
68
+ // See above.
69
+ new plejdPlatformAccessory_1.PlejdPlatformAccessory(this, accessory);
70
+ // link the accessory to your platform
71
+ this.api.registerPlatformAccessories(settings_1.PLUGIN_NAME, settings_1.PLATFORM_NAME, [accessory]);
72
+ }
73
+ }
74
+ }
75
+ onPlejdUpdates(identifier, state, dim) {
76
+ var _a, _b, _c, _d;
77
+ const uuid = (_a = this.userInputConfig.devices.find(d => d.identifier === identifier)) === null || _a === void 0 ? void 0 : _a.uuid;
78
+ if (uuid === undefined) {
79
+ this.log.warn(`Got updates on a device with identifier ${identifier} but it is not registered in HB settings`);
80
+ return;
81
+ }
82
+ const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
83
+ const device = this.userInputConfig.devices.find(dev => dev.identifier === identifier);
84
+ if (existingAccessory && device) {
85
+ if (device.isDimmer) {
86
+ const ser = existingAccessory.getService(this.Service.Lightbulb);
87
+ (_b = ser === null || ser === void 0 ? void 0 : ser.getCharacteristic(this.Characteristic.On)) === null || _b === void 0 ? void 0 : _b.updateValue(state);
88
+ ser === null || ser === void 0 ? void 0 : ser.getCharacteristic(this.Characteristic.Brightness).updateValue(dim === 0 ? 1 : ((100 / 255) * dim));
89
+ }
90
+ else {
91
+ (_d = (_c = existingAccessory.getService(this.Service.Switch)) === null || _c === void 0 ? void 0 : _c.getCharacteristic(this.Characteristic.On)) === null || _d === void 0 ? void 0 : _d.updateValue(state);
92
+ }
93
+ }
94
+ }
95
+ generateId(input) {
96
+ return this.api.hap.uuid.generate(input);
97
+ }
98
+ }
99
+ exports.PlejdPlatform = PlejdPlatform;
100
+ //# sourceMappingURL=plejdPlatform.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plejdPlatform.js","sourceRoot":"","sources":["../src/plejdPlatform.ts"],"names":[],"mappings":";;;AAEA,yCAAsE;AACtE,qEAAkE;AAElE,iDAA8C;AAE9C,MAAa,aAAa;IAUxB,YACkB,GAAW,EACX,MAAsB,EACtB,GAAQ;QAFR,QAAG,GAAH,GAAG,CAAQ;QACX,WAAM,GAAN,MAAM,CAAgB;QACtB,QAAG,GAAH,GAAG,CAAK;QAZV,YAAO,GAAmB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC;QAC/C,mBAAc,GAA0B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,cAAc,CAAC;QAKpF,oDAAoD;QACpC,gBAAW,GAAwB,EAAE,CAAC;QAOpD,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,iCAAiC,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACxE,mCAAmC;QACnC,MAAM,IAAI,GAAG,MAAM,CAAC,SAAS,CAAa,CAAC;QAC3C,KAAK,IAAI,CAAC,GAAC,CAAC,EAAC,CAAC,GAAC,IAAI,CAAC,MAAM,EAAC,CAAC,EAAE,EAAE;YAC9B,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,GAAG,uBAAY,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;YAC1D,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC,CAAC;SAC/D;QAED,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;QAC7E,IAAI,CAAC,eAAe,GAAG;YACrB,OAAO,EAAE,IAAI;YACb,SAAS,EAAE,SAAS;SACrB,CAAC;QACF,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,cAAc,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;QACrD,IAAI,CAAC,YAAY,GAAG,IAAI,2BAAY,CAAC,IAAI,CAAC,eAAe,EAAE,GAAG,EAAE,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QAEhG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,oBAAoB,EAAE,GAAG,EAAE;YACrC,IAAI,CAAC,eAAe,EAAE,CAAC;QACzB,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;KAGC;IACD,kBAAkB,CAAC,SAA4B;QAC7C,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,+BAA+B,EAAE,SAAS,CAAC,WAAW,CAAC,CAAC;QACtE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACnC,CAAC;IAED;;;;KAIC;IACD,eAAe;QACb,MAAM,KAAK,GAAG,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC5D,MAAM,aAAa,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;QAC9E,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE;YAC5B,IAAI,CAAC,GAAG,CAAC,6BAA6B,CAAC,sBAAW,EAAE,wBAAa,EAAE,aAAa,CAAC,CAAC;SACnF;QAED,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE;YACjD,MAAM,iBAAiB,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,SAAS,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC;YAE7F,IAAI,iBAAiB,EAAE;gBACrB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,0CAA0C,EAAE,iBAAiB,CAAC,WAAW,CAAC,CAAC;gBACzF,iBAAiB,CAAC,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC;gBAC1C,iBAAiB,CAAC,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC;gBAC5C,IAAI,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC;gBAExD,uDAAuD;gBACvD,yCAAyC;gBACzC,IAAI,+CAAsB,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;aACrD;iBAAM;gBACL,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,uBAAuB,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;gBACpD,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,iBAAiB,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;gBAC3E,SAAS,CAAC,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC;gBAElC,aAAa;gBACb,IAAI,+CAAsB,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;gBAE5C,sCAAsC;gBACtC,IAAI,CAAC,GAAG,CAAC,2BAA2B,CAAC,sBAAW,EAAE,wBAAa,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC;aAC/E;SACF;IACH,CAAC;IAED,cAAc,CAAC,UAAkB,EAAE,KAAa,EAAE,GAAY;;QAC5D,MAAM,IAAI,GAAG,MAAA,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,UAAU,CAAC,0CAAE,IAAI,CAAC;QACvF,IAAI,IAAI,KAAK,SAAS,EAAE;YACtB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,2CAA2C,UAAU,0CAA0C,CAAC,CAAC;YAC/G,OAAO;SACR;QACD,MAAM,iBAAiB,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,SAAS,CAAC,IAAI,KAAK,IAAK,CAAC,CAAC;QACvF,MAAM,MAAM,GAAG,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,UAAU,KAAK,UAAU,CAAC,CAAC;QACvF,IAAI,iBAAiB,IAAI,MAAM,EAAE;YAC/B,IAAI,MAAM,CAAC,QAAQ,EAAE;gBACnB,MAAM,GAAG,GAAG,iBAAiB,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;gBACjE,MAAA,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,iBAAiB,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC,0CAAE,WAAW,CAAC,KAAK,CAAC,CAAC;gBACnE,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,iBAAiB,CAAC,IAAI,CAAC,cAAc,CAAC,UAAU,EAClD,WAAW,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,GAAI,CAAC,CAAC,CAAC;aACtD;iBAAM;gBACL,MAAA,MAAA,iBAAiB,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,0CAC7C,iBAAiB,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC,0CACzC,WAAW,CAAC,KAAK,CAAC,CAAC;aACxB;SACF;IAEH,CAAC;IAEO,UAAU,CAAC,KAAa;QAC9B,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC3C,CAAC;CACF;AA7GD,sCA6GC"}
@@ -0,0 +1,24 @@
1
+ import { PlatformAccessory, CharacteristicValue } from 'homebridge';
2
+ import { PlejdPlatform } from './plejdPlatform';
3
+ /**
4
+ * Platform Accessory
5
+ * An instance of this class is created for each accessory your platform registers
6
+ * Each accessory may expose multiple services of different service types.
7
+ */
8
+ export declare class PlejdPlatformAccessory {
9
+ private readonly platform;
10
+ private readonly accessory;
11
+ private service;
12
+ private device;
13
+ /**
14
+ * These are just used to create a working example
15
+ * You should implement your own code to track the state of your accessory
16
+ */
17
+ private deviceState;
18
+ constructor(platform: PlejdPlatform, accessory: PlatformAccessory);
19
+ setOn(value: CharacteristicValue): Promise<void>;
20
+ getOn(): Promise<CharacteristicValue>;
21
+ setBrightness(value: CharacteristicValue): Promise<void>;
22
+ getBrightness(): Promise<CharacteristicValue>;
23
+ }
24
+ //# sourceMappingURL=plejdPlatformAccessory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plejdPlatformAccessory.d.ts","sourceRoot":"","sources":["../src/plejdPlatformAccessory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAG7E,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGhD;;;;GAIG;AACH,qBAAa,sBAAsB;IAc/B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAd5B,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,MAAM,CAAS;IAEvB;;;OAGG;IACH,OAAO,CAAC,WAAW,CAGjB;gBAGiB,QAAQ,EAAE,aAAa,EACvB,SAAS,EAAE,iBAAiB;IAkCzC,KAAK,CAAC,KAAK,EAAE,mBAAmB;IAWhC,KAAK,IAAI,OAAO,CAAC,mBAAmB,CAAC;IAKrC,aAAa,CAAC,KAAK,EAAE,mBAAmB;IAOxC,aAAa,IAAI,OAAO,CAAC,mBAAmB,CAAC;CAIpD"}
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PlejdPlatformAccessory = void 0;
4
+ const settings_1 = require("./settings");
5
+ /**
6
+ * Platform Accessory
7
+ * An instance of this class is created for each accessory your platform registers
8
+ * Each accessory may expose multiple services of different service types.
9
+ */
10
+ class PlejdPlatformAccessory {
11
+ constructor(platform, accessory) {
12
+ this.platform = platform;
13
+ this.accessory = accessory;
14
+ /**
15
+ * These are just used to create a working example
16
+ * You should implement your own code to track the state of your accessory
17
+ */
18
+ this.deviceState = {
19
+ On: false,
20
+ Brightness: 100,
21
+ };
22
+ this.device = this.accessory.context.device;
23
+ platform.log.debug(`Adding handler for a ${this.device.model} with id ${this.device.identifier}`);
24
+ // set accessory information
25
+ this.accessory.getService(this.platform.Service.AccessoryInformation)
26
+ .setCharacteristic(this.platform.Characteristic.Manufacturer, settings_1.PLATFORM_NAME)
27
+ .setCharacteristic(this.platform.Characteristic.Model, this.device.model)
28
+ .setCharacteristic(this.platform.Characteristic.SerialNumber, this.device.identifier.toString());
29
+ if (this.device.isDimmer) {
30
+ // get the LightBulb service if it exists, otherwise create a new LightBulb service
31
+ this.service = this.accessory.getService(this.platform.Service.Lightbulb) ||
32
+ this.accessory.addService(this.platform.Service.Lightbulb);
33
+ this.service.getCharacteristic(this.platform.Characteristic.Brightness)
34
+ .onGet(this.getBrightness.bind(this))
35
+ .onSet(this.setBrightness.bind(this));
36
+ }
37
+ else {
38
+ this.service = this.accessory.getService(this.platform.Service.Switch) ||
39
+ this.accessory.addService(this.platform.Service.Switch);
40
+ }
41
+ // register handlers for the On/Off Characteristic
42
+ this.service.getCharacteristic(this.platform.Characteristic.On)
43
+ .onSet(this.setOn.bind(this))
44
+ .onGet(this.getOn.bind(this));
45
+ this.service.setCharacteristic(this.platform.Characteristic.Name, this.device.name);
46
+ }
47
+ async setOn(value) {
48
+ this.deviceState.On = value;
49
+ this.platform.log.debug('Set Characteristic On', this.device.name, this.deviceState.On);
50
+ if (this.deviceState.On) {
51
+ this.platform.plejdService.turnOn(this.device.identifier);
52
+ }
53
+ else {
54
+ this.platform.plejdService.turnOff(this.device.identifier);
55
+ }
56
+ }
57
+ async getOn() {
58
+ this.platform.log.debug('Get Characteristic On', this.device.name, this.deviceState.On);
59
+ return this.deviceState.On;
60
+ }
61
+ async setBrightness(value) {
62
+ const dim = value;
63
+ this.deviceState.Brightness = dim;
64
+ this.platform.log.debug('Set Characteristic Brightness', this.device.name, dim);
65
+ this.platform.plejdService.turnOn(this.device.identifier, dim === 0 ? 1 : Math.round((2.55 * dim)));
66
+ }
67
+ async getBrightness() {
68
+ this.platform.log.debug('Get Characteristic Brightness', this.device.name, this.deviceState.Brightness);
69
+ return this.deviceState.Brightness;
70
+ }
71
+ }
72
+ exports.PlejdPlatformAccessory = PlejdPlatformAccessory;
73
+ //# sourceMappingURL=plejdPlatformAccessory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plejdPlatformAccessory.js","sourceRoot":"","sources":["../src/plejdPlatformAccessory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import { Logger } from 'homebridge';
2
+ import { UserInputConfig } from './model';
3
+ export declare class PlejdService {
4
+ private readonly config;
5
+ readonly log: Logger;
6
+ private readonly onUpdate;
7
+ private connectedPeripheral;
8
+ private pingIndex;
9
+ constructor(config: UserInputConfig, log: Logger, onUpdate: (identifier: number, state: number, dim?: number) => void);
10
+ turnOn(identifier: number, brightness?: number): void;
11
+ turnOff(identifier: number): void;
12
+ private stateChange;
13
+ private startConnection;
14
+ private discover;
15
+ private connectToPeripheral;
16
+ private discovered;
17
+ private plejdAuth;
18
+ private startPlejdPing;
19
+ private plejdPing;
20
+ private disconnect;
21
+ private gotData;
22
+ private plejdWrite;
23
+ private addressBuffer;
24
+ private dataCharacteristic;
25
+ }
26
+ //# sourceMappingURL=plejdService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plejdService.d.ts","sourceRoot":"","sources":["../src/plejdService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAe1C,qBAAa,YAAY;IAKjB,OAAO,CAAC,QAAQ,CAAC,MAAM;aACP,GAAG,EAAE,MAAM;IAC3B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAN/B,OAAO,CAAC,mBAAmB,CAA2B;IACtD,OAAO,CAAC,SAAS,CAAgB;gBAGV,MAAM,EAAE,eAAe,EACxB,GAAG,EAAE,MAAM,EACV,QAAQ,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,KAAK,IAAI;IAQ1F,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM;IAsB9C,OAAO,CAAC,UAAU,EAAE,MAAM;IAc1B,OAAO,CAAC,WAAW;IASnB,OAAO,CAAC,eAAe;IAOvB,OAAO,CAAC,QAAQ;IAchB,OAAO,CAAC,mBAAmB;IA6B3B,OAAO,CAAC,UAAU;IAwBlB,OAAO,CAAC,SAAS;IA2BjB,OAAO,CAAC,cAAc;IAmBtB,OAAO,CAAC,SAAS;IA0BjB,OAAO,CAAC,UAAU;IAoBlB,OAAO,CAAC,OAAO;IAiDf,OAAO,CAAC,UAAU;IASlB,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,kBAAkB;CAQ3B"}
@@ -0,0 +1,263 @@
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.PlejdService = void 0;
7
+ const plejdUtils_1 = require("./plejdUtils");
8
+ const crypto_1 = require("crypto");
9
+ const noble_1 = __importDefault(require("@abandonware/noble"));
10
+ const settings_1 = require("./settings");
11
+ const NOBLE_IS_POWER_ON = 'poweredOn';
12
+ class PlejdService {
13
+ constructor(config, log, onUpdate) {
14
+ this.config = config;
15
+ this.log = log;
16
+ this.onUpdate = onUpdate;
17
+ noble_1.default.on('stateChange', (state) => this.stateChange(state));
18
+ noble_1.default.on('warning', (msg) => this.log.warn('Noble warning: ', msg));
19
+ }
20
+ turnOn(identifier, brightness) {
21
+ const char = this.dataCharacteristic();
22
+ if (!char) {
23
+ this.log.warn('TurnOn characteristic not found');
24
+ return;
25
+ }
26
+ const command = (brightness !== undefined) ? '0098' : '0097';
27
+ let payload = Buffer.from((identifier).toString(16).padStart(2, '0') + '0110' + command + '01', 'hex');
28
+ if (brightness !== undefined) {
29
+ payload = Buffer.concat([payload, Buffer.from(brightness.toString(16).padStart(4, '0'), 'hex')]);
30
+ }
31
+ const addr = this.addressBuffer();
32
+ if (!addr) {
33
+ return;
34
+ }
35
+ const data = (0, plejdUtils_1.plejdEncodeDecode)(this.config.cryptoKey, addr, payload);
36
+ this.plejdWrite(char, data);
37
+ }
38
+ turnOff(identifier) {
39
+ const char = this.dataCharacteristic();
40
+ const addr = this.addressBuffer();
41
+ if (!char || !addr) {
42
+ return;
43
+ }
44
+ const payload = Buffer.from((identifier).toString(16).padStart(2, '0') + '0110009700', 'hex');
45
+ const data = (0, plejdUtils_1.plejdEncodeDecode)(this.config.cryptoKey, addr, payload);
46
+ this.plejdWrite(char, data);
47
+ }
48
+ // -------------- Private -------------- \\
49
+ stateChange(state) {
50
+ if (state !== NOBLE_IS_POWER_ON) {
51
+ this.log.debug('stateChange: Stopped | ' + state);
52
+ noble_1.default.stopScanning();
53
+ }
54
+ this.log.debug('stateChange: Started | ' + state);
55
+ this.startConnection();
56
+ }
57
+ startConnection() {
58
+ if (noble_1.default.state === NOBLE_IS_POWER_ON) {
59
+ noble_1.default.startScanning([settings_1.PLEJD_SERVICE_UUID], false);
60
+ noble_1.default.once('discover', (peripheral) => this.discover(peripheral));
61
+ }
62
+ }
63
+ discover(peripheral) {
64
+ this.log.info(`Discovered | ${peripheral.advertisement.localName} | addr: ${peripheral.address} | RSSI: ${peripheral.rssi} dB`);
65
+ noble_1.default.stopScanning();
66
+ peripheral.connect((error) => {
67
+ if (error) {
68
+ this.log.error(`Connecting failed | ${peripheral.advertisement.localName} | addr: ${peripheral.address}) - err: ${error}`);
69
+ return;
70
+ }
71
+ this.connectToPeripheral(peripheral);
72
+ });
73
+ }
74
+ connectToPeripheral(peripheral) {
75
+ this.log.info(`Connected | ${peripheral.advertisement.localName} (addr: ${peripheral.address})`);
76
+ this.connectedPeripheral = peripheral;
77
+ const services = [settings_1.PLEJD_SERVICE_UUID];
78
+ const characteristics = [
79
+ settings_1.PLEJD_CHARACTERISTIC_DATA_UUID,
80
+ settings_1.PLEJD_CHARACTERISTIC_LAST_DATA_UUID,
81
+ settings_1.PLEJD_CHARACTERISTIC_AUTH_UUID,
82
+ settings_1.PLEJD_CHARACTERISTIC_PING_UUID
83
+ ];
84
+ peripheral.discoverSomeServicesAndCharacteristics(services, characteristics, (error, services, characteristics) => {
85
+ if (error) {
86
+ this.log.error('Discover failed | ' + peripheral.advertisement.localName + ' (' + peripheral.address + ') | ' + error);
87
+ return;
88
+ }
89
+ this.discovered(peripheral, services, characteristics);
90
+ });
91
+ this.log.debug('Connected - Peripheral: ', peripheral);
92
+ peripheral.once('disconnect', () => {
93
+ this.log.info('Peripheral disconnected');
94
+ this.connectedPeripheral = null;
95
+ });
96
+ }
97
+ discovered(peripheral, services, characteristics) {
98
+ const authChar = characteristics.find((char) => char.uuid === settings_1.PLEJD_CHARACTERISTIC_AUTH_UUID);
99
+ const lastDataChar = characteristics.find((char) => char.uuid === settings_1.PLEJD_CHARACTERISTIC_LAST_DATA_UUID);
100
+ const pingChar = characteristics.find((char) => char.uuid === settings_1.PLEJD_CHARACTERISTIC_PING_UUID);
101
+ if (!authChar || !lastDataChar || !pingChar) {
102
+ this.log.error('Unable to extract characteristic during discovery', authChar, lastDataChar, pingChar);
103
+ return;
104
+ }
105
+ this.plejdAuth(authChar, () => {
106
+ this.startPlejdPing(pingChar);
107
+ lastDataChar.subscribe((error) => {
108
+ if (error) {
109
+ this.log.error('Error subscribing | ' + error);
110
+ return;
111
+ }
112
+ lastDataChar.on('data', (data, isNotification) => this.gotData(data, isNotification));
113
+ });
114
+ });
115
+ }
116
+ plejdAuth(authChar, callback) {
117
+ authChar.write(Buffer.from([0x00]), false, (error) => {
118
+ if (error) {
119
+ this.log.error('Error writing auth start | ' + error);
120
+ return;
121
+ }
122
+ authChar.read((error, data) => {
123
+ if (error) {
124
+ this.log.error('Error reading auth | ' + error);
125
+ return;
126
+ }
127
+ authChar.write((0, plejdUtils_1.plejdChalResp)(this.config.cryptoKey, data), false, (error) => {
128
+ if (error) {
129
+ this.log.error('Error writing auth chal | ' + error);
130
+ return;
131
+ }
132
+ callback();
133
+ });
134
+ });
135
+ });
136
+ }
137
+ startPlejdPing(pingChar) {
138
+ clearInterval(this.pingIndex);
139
+ this.pingIndex = setInterval(() => {
140
+ if (this.connectedPeripheral) {
141
+ this.plejdPing(pingChar, (pingOk) => {
142
+ if (pingOk === false) {
143
+ this.disconnect(() => {
144
+ this.startConnection();
145
+ });
146
+ }
147
+ });
148
+ }
149
+ else {
150
+ this.disconnect(() => {
151
+ this.startConnection();
152
+ });
153
+ }
154
+ }, 1000 * 60 * 3);
155
+ }
156
+ plejdPing(pingChar, callback) {
157
+ const ping = (0, crypto_1.randomBytes)(1);
158
+ pingChar.write(ping, false, (error) => {
159
+ if (error) {
160
+ this.log.error('Error sending ping | ' + error);
161
+ return callback(false);
162
+ }
163
+ pingChar.read((error, pong) => {
164
+ if (error) {
165
+ this.log.error('Error reading pong | ' + error);
166
+ return callback(false);
167
+ }
168
+ if (((ping[0] + 1) & 0xff) !== pong[0]) {
169
+ this.log.error('Ping failed: ' + ping[0] + ' ' + pong[0]);
170
+ callback(false);
171
+ }
172
+ else {
173
+ this.log.debug('Ping success: ' + ping[0] + ' ' + pong[0]);
174
+ callback(true);
175
+ }
176
+ });
177
+ });
178
+ }
179
+ disconnect(callback) {
180
+ clearInterval(this.pingIndex);
181
+ if (this.connectedPeripheral) {
182
+ this.log.info('Disconnecting peripheral');
183
+ this.connectedPeripheral.disconnect(() => {
184
+ this.connectedPeripheral = null;
185
+ if (callback) {
186
+ callback();
187
+ return;
188
+ }
189
+ });
190
+ }
191
+ if (callback) {
192
+ callback();
193
+ }
194
+ }
195
+ gotData(data, isNotification) {
196
+ this.log.debug(`GotData: data: ${data} - isNotification: ${isNotification}`);
197
+ const addr = this.addressBuffer();
198
+ if (!addr) {
199
+ return;
200
+ }
201
+ const decodedData = (0, plejdUtils_1.plejdEncodeDecode)(this.config.cryptoKey, addr, data);
202
+ let state = 0;
203
+ const id = parseInt(decodedData[0].toString(), 10);
204
+ const command = decodedData.toString('hex', 3, 5);
205
+ const argument = parseInt(decodedData.toString('hex', 5, 6), 10);
206
+ if (command === '001b') {
207
+ // time
208
+ const argument = parseInt((0, plejdUtils_1.reverseBuffer)(decodedData.slice(5, 9)).toString('hex'), 16);
209
+ const date = new Date(argument * 1000);
210
+ this.log.debug('Time sync: ' + date.toString());
211
+ return;
212
+ }
213
+ else if (command === '0021') {
214
+ // scene
215
+ this.log.debug('Trigger scene: ' + argument);
216
+ return;
217
+ }
218
+ else if (command === '00c8' || command === '0098') {
219
+ // 00c8, 0098 = state + dim
220
+ // state 0 or 1
221
+ state = argument;
222
+ const dim = parseInt(decodedData.toString('hex', 7, 8), 16);
223
+ this.log.debug(id + ' state: ' + state + ' dim: ' + dim);
224
+ this.onUpdate(id, state, dim);
225
+ }
226
+ else if (command === '0097') {
227
+ // 0097 = state only
228
+ // state 0 or 1
229
+ state = argument;
230
+ this.log.debug(id + ' state: ' + state);
231
+ this.onUpdate(id, state);
232
+ return;
233
+ }
234
+ else {
235
+ this.log.warn('Unknown command: ' + command + ' for device: ' + id + ' ' + (decodedData.toString('hex')));
236
+ return;
237
+ }
238
+ }
239
+ plejdWrite(dataChar, data) {
240
+ dataChar.write(data, false, (error) => {
241
+ if (error) {
242
+ this.log.error('Error writing data | ' + error);
243
+ return;
244
+ }
245
+ });
246
+ }
247
+ addressBuffer() {
248
+ if (this.connectedPeripheral) {
249
+ return (0, plejdUtils_1.reverseBuffer)(Buffer.from(String(this.connectedPeripheral.address).replace(/:/g, ''), 'hex'));
250
+ }
251
+ return null;
252
+ }
253
+ dataCharacteristic() {
254
+ if (this.connectedPeripheral && this.connectedPeripheral.services.length > 0) {
255
+ return this.connectedPeripheral.services[0].characteristics.find((char) => {
256
+ return char.uuid === settings_1.PLEJD_CHARACTERISTIC_DATA_UUID;
257
+ });
258
+ }
259
+ return null;
260
+ }
261
+ }
262
+ exports.PlejdService = PlejdService;
263
+ //# sourceMappingURL=plejdService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plejdService.js","sourceRoot":"","sources":["../src/plejdService.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /// <reference types="node" />
2
+ export declare function plejdChalResp(key: any, chal: any): Buffer;
3
+ export declare function plejdEncodeDecode(key: Buffer, addressBuffer: Buffer, data: Buffer): Buffer;
4
+ export declare function reverseBuffer(src: Buffer): Buffer;
5
+ //# sourceMappingURL=plejdUtils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plejdUtils.d.ts","sourceRoot":"","sources":["../src/plejdUtils.ts"],"names":[],"mappings":";AAEA,wBAAgB,aAAa,CAAC,GAAG,KAAA,EAAE,IAAI,KAAA,UAOtC;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAe1F;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CASjD"}
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.reverseBuffer = exports.plejdEncodeDecode = exports.plejdChalResp = void 0;
4
+ const crypto_1 = require("crypto");
5
+ function plejdChalResp(key, chal) {
6
+ const intermediate = (0, crypto_1.createHash)('sha256').update(xor(key, chal)).digest();
7
+ const part1 = intermediate.slice(0, 16);
8
+ const part2 = intermediate.slice(16);
9
+ return xor(part1, part2);
10
+ }
11
+ exports.plejdChalResp = plejdChalResp;
12
+ function plejdEncodeDecode(key, addressBuffer, data) {
13
+ const buf = Buffer.concat([addressBuffer, addressBuffer, addressBuffer.subarray(0, 4)]);
14
+ const cipher = (0, crypto_1.createCipheriv)('aes-128-ecb', key, '');
15
+ cipher.setAutoPadding(false);
16
+ let ct = cipher.update(buf).toString('hex');
17
+ ct += cipher.final().toString('hex');
18
+ const ctBuff = Buffer.from(ct, 'hex');
19
+ let output = '';
20
+ for (let i = 0, length = data.length; i < length; i++) {
21
+ output += String.fromCharCode(data[i] ^ ctBuff[i % 16]);
22
+ }
23
+ return Buffer.from(output, 'ascii');
24
+ }
25
+ exports.plejdEncodeDecode = plejdEncodeDecode;
26
+ function reverseBuffer(src) {
27
+ const buffer = Buffer.allocUnsafe(src.length);
28
+ for (let i = 0, j = src.length - 1; i <= j; ++i, --j) {
29
+ buffer[i] = src[j];
30
+ buffer[j] = src[i];
31
+ }
32
+ return buffer;
33
+ }
34
+ exports.reverseBuffer = reverseBuffer;
35
+ function xor(first, second) {
36
+ const result = Buffer.alloc(first.length);
37
+ for (let i = 0; i < first.length; i++) {
38
+ result[i] = first[i] ^ second[i];
39
+ }
40
+ return result;
41
+ }
42
+ //# sourceMappingURL=plejdUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plejdUtils.js","sourceRoot":"","sources":["../src/plejdUtils.ts"],"names":[],"mappings":";;;AAAA,mCAAoD;AAEpD,SAAgB,aAAa,CAAC,GAAG,EAAE,IAAI;IACrC,MAAM,YAAY,GAAG,IAAA,mBAAU,EAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IAE1E,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACxC,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAErC,OAAO,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AAC3B,CAAC;AAPD,sCAOC;AAED,SAAgB,iBAAiB,CAAC,GAAW,EAAE,aAAqB,EAAE,IAAY;IAChF,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,aAAa,EAAE,aAAa,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACxF,MAAM,MAAM,GAAG,IAAA,uBAAc,EAAC,aAAa,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;IACtD,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;IAE7B,IAAI,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC5C,EAAE,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACrC,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IAEtC,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,EAAE;QACrD,MAAM,IAAI,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;KACzD;IAED,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AACtC,CAAC;AAfD,8CAeC;AAED,SAAgB,aAAa,CAAC,GAAW;IACvC,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAE9C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE;QACpD,MAAM,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;QACnB,MAAM,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;KACpB;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AATD,sCASC;AAED,SAAS,GAAG,CAAC,KAAa,EAAE,MAAc;IACxC,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC1C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;QACrC,MAAM,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;KAClC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,22 @@
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 = "Plejd";
5
+ /**
6
+ * This must match the name of your plugin as defined the package.json
7
+ */
8
+ export declare const PLUGIN_NAME = "homebridge-plejd";
9
+ /**
10
+ * Lights and switches from Plejd
11
+ */
12
+ export declare const PLEJD_LIGHTS: string[];
13
+ export declare const PLEJD_SWITCHES: string[];
14
+ /**
15
+ * Plejd BLE UUIDs
16
+ */
17
+ export declare const PLEJD_SERVICE_UUID = "31ba000160854726be45040c957391b5";
18
+ export declare const PLEJD_CHARACTERISTIC_DATA_UUID = "31ba000460854726be45040c957391b5";
19
+ export declare const PLEJD_CHARACTERISTIC_LAST_DATA_UUID = "31ba000560854726be45040c957391b5";
20
+ export declare const PLEJD_CHARACTERISTIC_AUTH_UUID = "31ba000960854726be45040c957391b5";
21
+ export declare const PLEJD_CHARACTERISTIC_PING_UUID = "31ba000a60854726be45040c957391b5";
22
+ //# 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,UAAU,CAAC;AAErC;;GAEG;AACH,eAAO,MAAM,WAAW,qBAAqB,CAAC;AAE9C;;GAEG;AACH,eAAO,MAAM,YAAY,UAAiC,CAAC;AAC3D,eAAO,MAAM,cAAc,UAAwD,CAAC;AAEpF;;GAEG;AACH,eAAO,MAAM,kBAAkB,qCAAqC,CAAC;AACrE,eAAO,MAAM,8BAA8B,qCAAqC,CAAC;AACjF,eAAO,MAAM,mCAAmC,qCAAqC,CAAC;AACtF,eAAO,MAAM,8BAA8B,qCAAqC,CAAC;AACjF,eAAO,MAAM,8BAA8B,qCAAqC,CAAC"}
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PLEJD_CHARACTERISTIC_PING_UUID = exports.PLEJD_CHARACTERISTIC_AUTH_UUID = exports.PLEJD_CHARACTERISTIC_LAST_DATA_UUID = exports.PLEJD_CHARACTERISTIC_DATA_UUID = exports.PLEJD_SERVICE_UUID = exports.PLEJD_SWITCHES = exports.PLEJD_LIGHTS = 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 = 'Plejd';
8
+ /**
9
+ * This must match the name of your plugin as defined the package.json
10
+ */
11
+ exports.PLUGIN_NAME = 'homebridge-plejd';
12
+ /**
13
+ * Lights and switches from Plejd
14
+ */
15
+ exports.PLEJD_LIGHTS = ['DIM-01', 'DIM-02', 'LED-10'];
16
+ exports.PLEJD_SWITCHES = ['REL-02', 'REL-01-2P', 'DAL-01', 'SPR-01', 'CTR-01'];
17
+ /**
18
+ * Plejd BLE UUIDs
19
+ */
20
+ exports.PLEJD_SERVICE_UUID = '31ba000160854726be45040c957391b5';
21
+ exports.PLEJD_CHARACTERISTIC_DATA_UUID = '31ba000460854726be45040c957391b5';
22
+ exports.PLEJD_CHARACTERISTIC_LAST_DATA_UUID = '31ba000560854726be45040c957391b5';
23
+ exports.PLEJD_CHARACTERISTIC_AUTH_UUID = '31ba000960854726be45040c957391b5';
24
+ exports.PLEJD_CHARACTERISTIC_PING_UUID = '31ba000a60854726be45040c957391b5';
25
+ //# 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,OAAO,CAAC;AAErC;;GAEG;AACU,QAAA,WAAW,GAAG,kBAAkB,CAAC;AAE9C;;GAEG;AACU,QAAA,YAAY,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;AAC9C,QAAA,cAAc,GAAG,CAAC,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;AAEpF;;GAEG;AACU,QAAA,kBAAkB,GAAG,kCAAkC,CAAC;AACxD,QAAA,8BAA8B,GAAG,kCAAkC,CAAC;AACpE,QAAA,mCAAmC,GAAG,kCAAkC,CAAC;AACzE,QAAA,8BAA8B,GAAG,kCAAkC,CAAC;AACpE,QAAA,8BAA8B,GAAG,kCAAkC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "private": false,
3
+ "displayName": "Plejd",
4
+ "name": "homebridge-plejd",
5
+ "author": "Alexander Herlin",
6
+ "version": "1.1.3-beta.0",
7
+ "description": "Make the swedish BLE devices from Plejd work with homebridge.",
8
+ "license": "MIT",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git@github.com:Herlix/homebridge-plejd.git"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/Herlix/homebridge-plejd/issues"
15
+ },
16
+ "engines": {
17
+ "node": ">=14.18.1",
18
+ "homebridge": ">=1.3.5"
19
+ },
20
+ "main": "dist/index.js",
21
+ "scripts": {
22
+ "lint": "eslint src/**.ts --max-warnings=0",
23
+ "watch": "npm run build && npm link && nodemon",
24
+ "build": "rimraf ./dist && tsc",
25
+ "prepublishOnly": "npm run lint && npm run build"
26
+ },
27
+ "keywords": [
28
+ "homebridge-plugin",
29
+ "plejd"
30
+ ],
31
+ "dependencies": {
32
+ "@abandonware/noble": "^1.9.2-15"
33
+ },
34
+ "devDependencies": {
35
+ "@types/node": "^16.10.9",
36
+ "@types/noble": "^0.0.40",
37
+ "@typescript-eslint/eslint-plugin": "^5.0.0",
38
+ "@typescript-eslint/parser": "^5.0.0",
39
+ "eslint": "^8.0.1",
40
+ "homebridge": "^1.3.5",
41
+ "nodemon": "^2.0.13",
42
+ "rimraf": "^3.0.2",
43
+ "ts-node": "^10.3.0",
44
+ "typescript": "^4.4.4"
45
+ }
46
+ }
package/plejd.sh ADDED
@@ -0,0 +1,28 @@
1
+ #/bin/bash
2
+
3
+ UNAME=$(uname)
4
+ if [ $UNAME != 'Darwin' ]; then
5
+ echo "For now only works on mac"
6
+ exit 0
7
+ fi
8
+
9
+ PREFIX=$(npm config get prefix)
10
+ NODE_IBACKUP_DIR=$PREFIX/lib/node_modules/ibackuptool
11
+
12
+ if [ ! -d "$NODE_IBACKUP_DIR" ]; then
13
+ then
14
+ sudo npm i -g ibackuptool
15
+ echo "Installing ibackuptool https://github.com/richinfante/iphonebackuptools"
16
+ # To make it run on mac we need to fix the line breaks in the files.
17
+ sudo find $NODE_IBACKUP_DIR/**/*js -exec sudo dos2unix {} \;
18
+ echo "System preferences -> Security & Privacy -> Privacy -> tick Full disk access for terminal"
19
+ fi
20
+
21
+ RAW=$(ibackuptool -l -f json)
22
+ UUID=$(echo ${RAW} | sed 's/run backups.list //' | jq '.[0].udid' | sed 's/"//g')
23
+ mkdir temp
24
+ Q=$(sudo ibackuptool -b ${UUID} -r backup.files --extract ./temp --regex-filter '\.(site)$')
25
+ mv temp/App/com.plejd.consumer.light/Documents/**/*.site ./temp/site.json
26
+ cat ./temp/site.json | jq '.PlejdMesh.CryptoKey' | sed 's/-//g' | sed 's/"//g'
27
+ cat ./temp/site.json | jq '.PlejdMesh._outputAddresses' | grep -v '\$type' | jq '.[][]'
28
+ rm -rf temp