homebridge-smarthq-client 1.0.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 +21 -0
- package/Readme.md +138 -0
- package/config.schema.json +146 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/platform.d.ts +40 -0
- package/dist/platform.js +243 -0
- package/dist/platform.js.map +1 -0
- package/dist/refrigerator/controlLock.d.ts +19 -0
- package/dist/refrigerator/controlLock.js +85 -0
- package/dist/refrigerator/controlLock.js.map +1 -0
- package/dist/refrigerator/convertibleDrawer.d.ts +27 -0
- package/dist/refrigerator/convertibleDrawer.js +317 -0
- package/dist/refrigerator/convertibleDrawer.js.map +1 -0
- package/dist/refrigerator/dispenserLight.d.ts +19 -0
- package/dist/refrigerator/dispenserLight.js +85 -0
- package/dist/refrigerator/dispenserLight.js.map +1 -0
- package/dist/refrigerator/energy.d.ts +19 -0
- package/dist/refrigerator/energy.js +93 -0
- package/dist/refrigerator/energy.js.map +1 -0
- package/dist/refrigerator/freezer.d.ts +41 -0
- package/dist/refrigerator/freezer.js +188 -0
- package/dist/refrigerator/freezer.js.map +1 -0
- package/dist/refrigerator/iceMaker.d.ts +19 -0
- package/dist/refrigerator/iceMaker.js +81 -0
- package/dist/refrigerator/iceMaker.js.map +1 -0
- package/dist/refrigerator/interiorLight.d.ts +21 -0
- package/dist/refrigerator/interiorLight.js +100 -0
- package/dist/refrigerator/interiorLight.js.map +1 -0
- package/dist/refrigerator/refrigerator.d.ts +41 -0
- package/dist/refrigerator/refrigerator.js +204 -0
- package/dist/refrigerator/refrigerator.js.map +1 -0
- package/dist/refrigerator/refrigeratorAlerts.d.ts +36 -0
- package/dist/refrigerator/refrigeratorAlerts.js +204 -0
- package/dist/refrigerator/refrigeratorAlerts.js.map +1 -0
- package/dist/refrigerator/sabbathMode.d.ts +20 -0
- package/dist/refrigerator/sabbathMode.js +91 -0
- package/dist/refrigerator/sabbathMode.js.map +1 -0
- package/dist/refrigerator/temperatureUnits.d.ts +21 -0
- package/dist/refrigerator/temperatureUnits.js +147 -0
- package/dist/refrigerator/temperatureUnits.js.map +1 -0
- package/dist/refrigerator/turboCoolMode.d.ts +23 -0
- package/dist/refrigerator/turboCoolMode.js +134 -0
- package/dist/refrigerator/turboCoolMode.js.map +1 -0
- package/dist/refrigerator/waterFilter.d.ts +19 -0
- package/dist/refrigerator/waterFilter.js +89 -0
- package/dist/refrigerator/waterFilter.js.map +1 -0
- package/dist/refrigeratorServices.d.ts +5 -0
- package/dist/refrigeratorServices.js +54 -0
- package/dist/refrigeratorServices.js.map +1 -0
- package/dist/settings.d.ts +12 -0
- package/dist/settings.js +13 -0
- package/dist/settings.js.map +1 -0
- package/dist/smartHqApi.d.ts +29 -0
- package/dist/smartHqApi.js +267 -0
- package/dist/smartHqApi.js.map +1 -0
- package/dist/smarthq-types.d.ts +29 -0
- package/dist/smarthq-types.js +2 -0
- package/dist/smarthq-types.js.map +1 -0
- package/eslint.config.js +12 -0
- package/images/homebridge.svg +1 -0
- package/package.json +61 -0
- package/src/@types/homebridge-lib.d.ts +14 -0
- package/src/index.ts +11 -0
- package/src/platform.ts +300 -0
- package/src/refrigerator/controlLock.ts +103 -0
- package/src/refrigerator/convertibleDrawer.ts +381 -0
- package/src/refrigerator/dispenserLight.ts +103 -0
- package/src/refrigerator/energy.ts +106 -0
- package/src/refrigerator/freezer.ts +227 -0
- package/src/refrigerator/iceMaker.ts +100 -0
- package/src/refrigerator/interiorLight.ts +118 -0
- package/src/refrigerator/refrigerator.ts +241 -0
- package/src/refrigerator/refrigeratorAlerts.ts +228 -0
- package/src/refrigerator/sabbathMode.ts +111 -0
- package/src/refrigerator/temperatureUnits.ts +178 -0
- package/src/refrigerator/turboCoolMode.ts +164 -0
- package/src/refrigerator/waterFilter.ts +107 -0
- package/src/refrigeratorServices.ts +60 -0
- package/src/settings.ts +14 -0
- package/src/smartHqApi.ts +305 -0
- package/src/smarthq-types.ts +31 -0
- package/tsconfig.json +24 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ceb400
|
|
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,138 @@
|
|
|
1
|
+
<img src="images/homebridge.svg" width="100" height="100">
|
|
2
|
+
|
|
3
|
+
# Homebridge-SmartHQ Client
|
|
4
|
+
|
|
5
|
+
A homebridge plugin for GE appliances using the SmartHQ API s (Identity and Access Management API, Digital Twin API). Currently only services for a refrigerator are implemented.
|
|
6
|
+
|
|
7
|
+
The refrigerator services include controls for:
|
|
8
|
+
* refrigerator temperature
|
|
9
|
+
* freezer temperature
|
|
10
|
+
* controls lock
|
|
11
|
+
* convertible drawer modes
|
|
12
|
+
* dispenser light
|
|
13
|
+
* icemaker
|
|
14
|
+
* interior light
|
|
15
|
+
* sabbath mode
|
|
16
|
+
* temperature units
|
|
17
|
+
* turbo cool modes refrigerator & freezer
|
|
18
|
+
* water filter maintenance (see notes)
|
|
19
|
+
* additional switches are used to implement notifications
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
Option 1: Homebridge UI
|
|
26
|
+
|
|
27
|
+
Go to the 'Plugins' page, search for homebridge-smarthq-client, and click 'Install'.
|
|
28
|
+
|
|
29
|
+
Option 2: Manually
|
|
30
|
+
|
|
31
|
+
Run the following command to install the plugin globally:
|
|
32
|
+
```
|
|
33
|
+
$ sudo npm install homebridge-smarthq-client -g
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
## Requirements
|
|
39
|
+
The SmartHQ API uses an OAuth 2.0 authentication process. The steps required to setup an account in order to use the API are
|
|
40
|
+
|
|
41
|
+
* Follow the steps at [Get Started - SmartHQ Docs](https://docs.smarthq.com/get-started/)
|
|
42
|
+
(The Callback URL specified in step 2.4 must match the corresponding field in the plugin config setup (recommended http://localhost:8888/callback)
|
|
43
|
+
|
|
44
|
+
* When step 2 from Get Started is complete and you have created an app, click on the app to display your apps page. Find the Credentials tab and copy the **Client Id**, **Client Secret** and **Callback URL** to the plugin config.
|
|
45
|
+
## Configuration
|
|
46
|
+
|
|
47
|
+
Use the Homebridge UI to configure this plugin. See **Requirements** for steps to obtain a Client Id and Client Secret.
|
|
48
|
+
|
|
49
|
+
* Select the services you want to add for the appliance in the plugin config.
|
|
50
|
+
|
|
51
|
+
* Select Logging options.
|
|
52
|
+
*Plugin Debug Logging* will log additional messages to the Homebridge log.
|
|
53
|
+
*Display Service Details* will log sorted information about all services for each discovered device.
|
|
54
|
+
(This info is used to add support for other appliances.)
|
|
55
|
+
|
|
56
|
+
* Save plugin config and restart child bridge.
|
|
57
|
+
|
|
58
|
+
Or manually edit the config file with
|
|
59
|
+
```
|
|
60
|
+
{
|
|
61
|
+
"name": "SmartHQ Client",
|
|
62
|
+
"clientId": "your client id",
|
|
63
|
+
"clientSecret": "your client secret",
|
|
64
|
+
"redirectUri": "http://localhost:8888/callback",
|
|
65
|
+
"addControlLock": false,
|
|
66
|
+
"addConvertibleDrawer": false,
|
|
67
|
+
"addDispenserLight": false,
|
|
68
|
+
"addIceMaker": false,
|
|
69
|
+
"addInteriorLight": false,
|
|
70
|
+
"addSabbathMode": false,
|
|
71
|
+
"addTemperatureUnits": false,
|
|
72
|
+
"addEnergyMonitor": false,
|
|
73
|
+
"addTurboCool": false,
|
|
74
|
+
"addWaterFilter": false,
|
|
75
|
+
"addAlerts": false,
|
|
76
|
+
"debugLogging": false,
|
|
77
|
+
"debugServices": false,
|
|
78
|
+
"_bridge": {
|
|
79
|
+
"name": "SmartHQ Bridge",
|
|
80
|
+
"username": "0E:23:87:36:1A:C8",
|
|
81
|
+
"port": 34603
|
|
82
|
+
},
|
|
83
|
+
"platform": "SmartHqPlatform"
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
## Initial Authentication
|
|
89
|
+
(*If access token does not exist*). Check the Homebridge log for a highlighted localhost URL.
|
|
90
|
+
```
|
|
91
|
+
=======================================================================
|
|
92
|
+
Click to login for SmartHQ Auth setup ===>: http://localhost:8888/login
|
|
93
|
+
=======================================================================
|
|
94
|
+
```
|
|
95
|
+
Click on the URL to be redirected to a SmartHQ authorization screen.
|
|
96
|
+
Login to your SmartHQ account to complete the process.
|
|
97
|
+
Once an access (and refresh) token have been saved this step will only be needed if the file
|
|
98
|
+
used to store your tokens is deleted.
|
|
99
|
+
When an access token expires the plugin will use the refresh token to obtain a new access token.
|
|
100
|
+
|
|
101
|
+
## Notifications
|
|
102
|
+
|
|
103
|
+
API device alerts are monitored for the following conditions:
|
|
104
|
+
* Door left open
|
|
105
|
+
* Temperature alert (either fridge or freezer)
|
|
106
|
+
* Water pitcher leak
|
|
107
|
+
* Filter maintenance
|
|
108
|
+
* Firmware
|
|
109
|
+
|
|
110
|
+
If selected during configuration, switches are added that will be turned on temporarily
|
|
111
|
+
when a corresponding alert is triggered.
|
|
112
|
+
Using these switches in conjunction with a 3rd party service (e.g PushOver, PushCutter etc)
|
|
113
|
+
an Apple Home automation can be set up to issue notifications for your iOS devices.
|
|
114
|
+
|
|
115
|
+
These switches will appear in Accessories as *Alert Door*, *Alert Temp*, *Alert Leak*, *Alert Filter*, *Alert Firm*
|
|
116
|
+
## Documentation
|
|
117
|
+
|
|
118
|
+
[SmartHQ Documentation](https://developer.smarthq.com/)
|
|
119
|
+
|
|
120
|
+
## Notes
|
|
121
|
+
The *water filter maintenance* option uses the Filter Maintenance Service in the Homebridge API.
|
|
122
|
+
The service exists in HomeKit but has not been implemented in the Apple Home app.
|
|
123
|
+
If selected in the plugin config you will notice a tile on the Homebridge Accessories page but there
|
|
124
|
+
will not be any tile/device shown in the Home app.
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
## Feedback
|
|
128
|
+
|
|
129
|
+
If you have any feedback, please reach out at: ceb40win@outlook.com
|
|
130
|
+
|
|
131
|
+
If you have GE smart appliances other than refrigerator you can capture
|
|
132
|
+
the following information (after adding the appliance to your SmartHQ account)
|
|
133
|
+
* Update the plugin config to select *Display Service Details*
|
|
134
|
+
* Restart the child bridge.
|
|
135
|
+
* Copy log output including 'SmartHQ Discovered device: newDevice Model: PVD28BYNIFS'
|
|
136
|
+
plus all logged services and forward the file to me.
|
|
137
|
+
As my time permits I will attempt to add support for new devices.
|
|
138
|
+
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
{
|
|
2
|
+
"pluginAlias": "SmartHqPlatform",
|
|
3
|
+
"pluginType": "platform",
|
|
4
|
+
"singular": true,
|
|
5
|
+
"schema": {
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["clientId", "clientSecret"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"clientId": {
|
|
10
|
+
"type": "string",
|
|
11
|
+
"title": "SmartHQ Client ID",
|
|
12
|
+
"x-schema-form": {
|
|
13
|
+
"type": "password"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"clientSecret": {
|
|
17
|
+
"type": "string",
|
|
18
|
+
"title": "SmartHQ Client Secret",
|
|
19
|
+
"x-schema-form": {
|
|
20
|
+
"type": "password"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"redirectUri": {
|
|
24
|
+
"type": "string",
|
|
25
|
+
"format": "uri",
|
|
26
|
+
"title": "OAuth Redirect URI (must match the one defined for SmartHQ app @ https://developer.smarthq.com/user/???/apps",
|
|
27
|
+
"default": "http://localhost:8888/callback"
|
|
28
|
+
},
|
|
29
|
+
"addControlLock": {
|
|
30
|
+
"type": "boolean",
|
|
31
|
+
"title": "Add Controls Lock",
|
|
32
|
+
"default": false
|
|
33
|
+
},
|
|
34
|
+
"addConvertibleDrawer": {
|
|
35
|
+
"type": "boolean",
|
|
36
|
+
"title": "Add Convertible Drawer Controls",
|
|
37
|
+
"default": false
|
|
38
|
+
},
|
|
39
|
+
"addDispenserLight": {
|
|
40
|
+
"type": "boolean",
|
|
41
|
+
"title": "Add Dispenser Light Control",
|
|
42
|
+
"default": false
|
|
43
|
+
},
|
|
44
|
+
"addIceMaker": {
|
|
45
|
+
"type": "boolean",
|
|
46
|
+
"title": "Add Ice Maker Control",
|
|
47
|
+
"default": false
|
|
48
|
+
},
|
|
49
|
+
"addInteriorLight": {
|
|
50
|
+
"type": "boolean",
|
|
51
|
+
"title": "Add Interior Light Control",
|
|
52
|
+
"default": false
|
|
53
|
+
},
|
|
54
|
+
"addSabbathMode": {
|
|
55
|
+
"type": "boolean",
|
|
56
|
+
"title": "Add Sabbath Mode Control",
|
|
57
|
+
"default": false
|
|
58
|
+
},
|
|
59
|
+
"addTemperatureUnits": {
|
|
60
|
+
"type": "boolean",
|
|
61
|
+
"title": "Add Temperature Units Control",
|
|
62
|
+
"default": false
|
|
63
|
+
},
|
|
64
|
+
"addEnergyMonitor": {
|
|
65
|
+
"type": "boolean",
|
|
66
|
+
"title": "Add Energy Monitor",
|
|
67
|
+
"default": false
|
|
68
|
+
},
|
|
69
|
+
"addTurboCool": {
|
|
70
|
+
"type": "boolean",
|
|
71
|
+
"title": "Add Turbo Cool Controls",
|
|
72
|
+
"default": false
|
|
73
|
+
},
|
|
74
|
+
"addWaterFilter": {
|
|
75
|
+
"type": "boolean",
|
|
76
|
+
"title": "Add Water Filter Status",
|
|
77
|
+
"default": false
|
|
78
|
+
},
|
|
79
|
+
"addAlerts": {
|
|
80
|
+
"type": "boolean",
|
|
81
|
+
"title": "Add Alert Notifications",
|
|
82
|
+
"default": false
|
|
83
|
+
},
|
|
84
|
+
"debugLogging": {
|
|
85
|
+
"type": "boolean",
|
|
86
|
+
"title": "Plugin Debug Logging w/Chalk Colors",
|
|
87
|
+
"default": false
|
|
88
|
+
},
|
|
89
|
+
"debugServices": {
|
|
90
|
+
"type": "boolean",
|
|
91
|
+
"title": "Display Service Details for all discovered services",
|
|
92
|
+
"default": false
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
"layout": [
|
|
97
|
+
{
|
|
98
|
+
"type": "section",
|
|
99
|
+
"title": "Authentication Settings",
|
|
100
|
+
"items": [
|
|
101
|
+
{
|
|
102
|
+
"description": "Required SmartHQ API authentication settings.",
|
|
103
|
+
"items": [
|
|
104
|
+
"clientId",
|
|
105
|
+
"clientSecret",
|
|
106
|
+
"redirectUri"
|
|
107
|
+
]
|
|
108
|
+
}
|
|
109
|
+
]
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
"type": "section",
|
|
113
|
+
"title": "Refrigerator Services",
|
|
114
|
+
"expandable": true,
|
|
115
|
+
"expanded": false,
|
|
116
|
+
"items": [
|
|
117
|
+
{
|
|
118
|
+
"description": "Include the selected refrigerator services.",
|
|
119
|
+
"items": [
|
|
120
|
+
"addConvertibleDrawer",
|
|
121
|
+
"addControlLock",
|
|
122
|
+
"addDispenserLight",
|
|
123
|
+
"addEnergyMonitor",
|
|
124
|
+
"addIceMaker",
|
|
125
|
+
"addInteriorLight",
|
|
126
|
+
"addSabbathMode",
|
|
127
|
+
"addTemperatureUnits",
|
|
128
|
+
"addTurboCool",
|
|
129
|
+
"addWaterFilter",
|
|
130
|
+
"addAlerts"
|
|
131
|
+
]
|
|
132
|
+
}
|
|
133
|
+
]
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
"type": "section",
|
|
137
|
+
"title": "Logging Options",
|
|
138
|
+
"expandable": true,
|
|
139
|
+
"expanded": false,
|
|
140
|
+
"items": [
|
|
141
|
+
"debugLogging",
|
|
142
|
+
"debugServices"
|
|
143
|
+
]
|
|
144
|
+
}
|
|
145
|
+
]
|
|
146
|
+
}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { SmartHqPlatform } from './platform.js';
|
|
2
|
+
import { PLATFORM_NAME } from './settings.js';
|
|
3
|
+
/**
|
|
4
|
+
* This method registers the platform with Homebridge
|
|
5
|
+
*/
|
|
6
|
+
export default (api) => {
|
|
7
|
+
api.registerPlatform(PLATFORM_NAME, SmartHqPlatform);
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C;;GAEG;AACH,eAAe,CAAC,GAAQ,EAAE,EAAE;IAC1B,GAAG,CAAC,gBAAgB,CAAC,aAAa,EAAE,eAAe,CAAC,CAAC;AACvD,CAAC,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { API, Logging, PlatformConfig, PlatformAccessory, Service, Characteristic } from 'homebridge';
|
|
2
|
+
import { SmartHqApi } from './smartHqApi.js';
|
|
3
|
+
import { EventEmitter } from 'node:events';
|
|
4
|
+
import { DevService } from './smarthq-types.js';
|
|
5
|
+
export declare class SmartHqPlatform {
|
|
6
|
+
readonly log: Logging;
|
|
7
|
+
readonly config: PlatformConfig;
|
|
8
|
+
private readonly api;
|
|
9
|
+
readonly Service: typeof Service;
|
|
10
|
+
readonly Characteristic: typeof Characteristic;
|
|
11
|
+
readonly accessories: Map<string, PlatformAccessory>;
|
|
12
|
+
readonly discoveredCacheUUIDs: string[];
|
|
13
|
+
readonly tokenPath: string;
|
|
14
|
+
private oauthServer?;
|
|
15
|
+
expires: number;
|
|
16
|
+
readonly smartHqApi: SmartHqApi;
|
|
17
|
+
authEmitter: EventEmitter;
|
|
18
|
+
serviceDeviceType: string;
|
|
19
|
+
serviceType: string;
|
|
20
|
+
constructor(log: Logging, config: PlatformConfig, api: API);
|
|
21
|
+
/**================================================================
|
|
22
|
+
* If no token file exists, start the OAuth process.
|
|
23
|
+
* In this process, we start a local express server to handle the redirect
|
|
24
|
+
* from the SmartHQ authorization endpoint.
|
|
25
|
+
* When the user clicks the link in Homebridge UI, they will be directed to the /login route
|
|
26
|
+
* which will redirect to SmartHQ authorization endpoint to obtain authorization code.
|
|
27
|
+
* After user login, SmartHQ authorization endpoint will redirect to whatever url:port/path was configured
|
|
28
|
+
* with authorization code in the query parameter.
|
|
29
|
+
* We will use this code to obtain access token and refresh token
|
|
30
|
+
*================================================================*/
|
|
31
|
+
startOAuth(): Promise<void>;
|
|
32
|
+
extractPortFromRedirectUri(redirectUri: string): {
|
|
33
|
+
port: number;
|
|
34
|
+
pathname: string;
|
|
35
|
+
};
|
|
36
|
+
configureAccessory(accessory: PlatformAccessory): void;
|
|
37
|
+
private discoverDevices;
|
|
38
|
+
debug(color: string, message: string): void;
|
|
39
|
+
deviceSupportsThisService(deviceServices: DevService[], serviceDeviceType: string, serviceType: string, domainType: string): boolean;
|
|
40
|
+
}
|
package/dist/platform.js
ADDED
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import express from 'express';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import { stringify, parse } from 'querystring';
|
|
6
|
+
import { SmartHqApi } from './smartHqApi.js';
|
|
7
|
+
import { EventEmitter } from 'node:events';
|
|
8
|
+
import { PLATFORM_NAME, PLUGIN_NAME, AUTH_URL, TOKEN_STORE } from './settings.js';
|
|
9
|
+
import { setupRefrigeratorServices } from './refrigeratorServices.js';
|
|
10
|
+
export class SmartHqPlatform {
|
|
11
|
+
log;
|
|
12
|
+
config;
|
|
13
|
+
api;
|
|
14
|
+
Service;
|
|
15
|
+
Characteristic;
|
|
16
|
+
// this is used to track restored cached accessories
|
|
17
|
+
accessories = new Map();
|
|
18
|
+
discoveredCacheUUIDs = [];
|
|
19
|
+
tokenPath;
|
|
20
|
+
oauthServer;
|
|
21
|
+
expires;
|
|
22
|
+
smartHqApi;
|
|
23
|
+
authEmitter;
|
|
24
|
+
serviceDeviceType = '';
|
|
25
|
+
serviceType = '';
|
|
26
|
+
constructor(log, config, api) {
|
|
27
|
+
this.log = log;
|
|
28
|
+
this.config = config;
|
|
29
|
+
this.api = api;
|
|
30
|
+
this.api = api;
|
|
31
|
+
this.Service = api.hap.Service;
|
|
32
|
+
this.Characteristic = api.hap.Characteristic;
|
|
33
|
+
this.expires = 0;
|
|
34
|
+
this.tokenPath = path.join(this.api.user.persistPath(), TOKEN_STORE);
|
|
35
|
+
this.authEmitter = new EventEmitter();
|
|
36
|
+
chalk.level = 1; // Enable chalk colors
|
|
37
|
+
this.smartHqApi = new SmartHqApi(this);
|
|
38
|
+
// Validate required configuration parameters
|
|
39
|
+
if (!config.clientId || !config.clientSecret || !config.redirectUri) {
|
|
40
|
+
this.log.error('Missing required config parameter.');
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
this.api.on('didFinishLaunching', async () => {
|
|
44
|
+
try {
|
|
45
|
+
this.debug('red', '(SmartHQ OAuth2 authentication starting)');
|
|
46
|
+
await this.startOAuth();
|
|
47
|
+
this.debug('blue', '(SmartHQ OAuth2 authentication completed)');
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
this.log.error(chalk.red('SmartHQ OAuth2 authentication failed:'), error);
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
// Listen for authComplete event to start device discovery
|
|
54
|
+
this.authEmitter.on('authComplete', async () => {
|
|
55
|
+
this.debug('green', 'Auth complete event received, starting device discovery');
|
|
56
|
+
await this.discoverDevices();
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
/**================================================================
|
|
60
|
+
* If no token file exists, start the OAuth process.
|
|
61
|
+
* In this process, we start a local express server to handle the redirect
|
|
62
|
+
* from the SmartHQ authorization endpoint.
|
|
63
|
+
* When the user clicks the link in Homebridge UI, they will be directed to the /login route
|
|
64
|
+
* which will redirect to SmartHQ authorization endpoint to obtain authorization code.
|
|
65
|
+
* After user login, SmartHQ authorization endpoint will redirect to whatever url:port/path was configured
|
|
66
|
+
* with authorization code in the query parameter.
|
|
67
|
+
* We will use this code to obtain access token and refresh token
|
|
68
|
+
*================================================================*/
|
|
69
|
+
async startOAuth() {
|
|
70
|
+
const path = this.tokenPath;
|
|
71
|
+
if (!fs.existsSync(path)) {
|
|
72
|
+
this.debug('blue', '=== file does not exist starting OAuth process ===');
|
|
73
|
+
this.debug('red', ' Starting localhost server to handle OAuth redirects');
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
this.debug('red', ' Returning because token path exists, emitting authComplete');
|
|
77
|
+
this.authEmitter.emit('authComplete');
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const url = new URL(this.config.redirectUri);
|
|
81
|
+
const pathname = url.pathname;
|
|
82
|
+
const port = parseInt(url.port, 10);
|
|
83
|
+
this.debug('blue', ' Redirect URI port: ' + port + ' , ' + pathname);
|
|
84
|
+
const app = express();
|
|
85
|
+
// By clicking on the link in Homebridge UI (Logs), user will be directed to the /login route
|
|
86
|
+
// which will redirect to SmartHQ authorization endpoint to obtain authorization code
|
|
87
|
+
this.log.info(chalk.blue("======================================================================="));
|
|
88
|
+
this.log.info("Click to login for SmartHQ Auth setup ===>: " + chalk.red("http://localhost:" + port + "/login"));
|
|
89
|
+
this.log.info(chalk.blue("======================================================================="));
|
|
90
|
+
// Clicking above link in Homebridge UI will redirect to SmartHQ authorization endpoint
|
|
91
|
+
app.get('/login', async (_req, res) => {
|
|
92
|
+
try {
|
|
93
|
+
const url = AUTH_URL + '?' + stringify({
|
|
94
|
+
response_type: 'code',
|
|
95
|
+
client_id: this.config.clientId,
|
|
96
|
+
redirect_uri: this.config.redirectUri
|
|
97
|
+
});
|
|
98
|
+
this.debug('blue', "Redirecting to: " + url);
|
|
99
|
+
res.redirect(url); ///====> Redirect to SmartHQ authorization endpoint
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
this.log.error('SmartHQ /login error:', error);
|
|
103
|
+
res.status(500).send('Authentication /login failed: ' + error);
|
|
104
|
+
}
|
|
105
|
+
;
|
|
106
|
+
});
|
|
107
|
+
// After user login, SmartHQ authorization endpoint will redirect to whatever url:port/path was configured
|
|
108
|
+
// with authorization code in the query parameter.
|
|
109
|
+
// We will use this code to obtain access token and refresh token
|
|
110
|
+
app.get(pathname, async (req, res) => {
|
|
111
|
+
try {
|
|
112
|
+
// Parse the request URL
|
|
113
|
+
const query = parse(req.url.split('?')[1]);
|
|
114
|
+
const code = query.code?.toString() || '';
|
|
115
|
+
this.debug('blue', 'An authorization code was returned: ' + code);
|
|
116
|
+
this.debug('blue', 'Now exchanging code for access token...');
|
|
117
|
+
if (!code) {
|
|
118
|
+
this.log.error('No code found in callback URL for SmartHQ OAuth');
|
|
119
|
+
}
|
|
120
|
+
await this.smartHqApi.exchangeCodeForToken(code);
|
|
121
|
+
res.send(`
|
|
122
|
+
<h2>SmartHQ Connected</h2>
|
|
123
|
+
<p>Authorization token saved to file.</p>
|
|
124
|
+
<p>You may close this window.</p>
|
|
125
|
+
`);
|
|
126
|
+
// Emit event to indicate authentication is complete
|
|
127
|
+
this.authEmitter.emit('authComplete');
|
|
128
|
+
this.log.success('SmartHQ authentication completed');
|
|
129
|
+
setTimeout(() => this.oauthServer?.close(), 1000);
|
|
130
|
+
this.debug('blue', 'OAuth server has been closed.');
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
this.log.error('SmartHQ OAuth failed', error);
|
|
135
|
+
res.status(500).send('Authentication failed: ' + error);
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
this.oauthServer = app.listen(port, () => {
|
|
139
|
+
this.log.info(`SmartHQ OAuth listening on ${port}`);
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
// Extract port and pathname from redirect URI
|
|
143
|
+
extractPortFromRedirectUri(redirectUri) {
|
|
144
|
+
const url = new URL(redirectUri);
|
|
145
|
+
const pathname = url.pathname;
|
|
146
|
+
const port = parseInt(url.port, 10);
|
|
147
|
+
return { port, pathname };
|
|
148
|
+
}
|
|
149
|
+
configureAccessory(accessory) {
|
|
150
|
+
this.log.info('Loading accessory from cache:', accessory.displayName);
|
|
151
|
+
// add the restored accessory to the accessories cache, so we can track if it has already been registered
|
|
152
|
+
this.accessories.set(accessory.UUID, accessory);
|
|
153
|
+
}
|
|
154
|
+
async discoverDevices() {
|
|
155
|
+
this.debug('yellow', '(discoverDevices) Starting device discovery...');
|
|
156
|
+
let devices = [];
|
|
157
|
+
devices = await this.smartHqApi.getAppliances();
|
|
158
|
+
// loop over the discovered devices and register each one if it has not already been registered
|
|
159
|
+
if (!devices || devices.length === 0) {
|
|
160
|
+
this.log.warn(chalk.yellow('No SmartHQ devices found for this account.'));
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
for (const device of devices) {
|
|
164
|
+
this.log.info(chalk.yellow(`SmartHQ Discovered device: ${device.nickname} Model: ${device.model}`));
|
|
165
|
+
// Used to acquire service IDs and service deviceTypes for deviceServiceState queries
|
|
166
|
+
const deviceServices = await this.smartHqApi.getDeviceServices(device.deviceId);
|
|
167
|
+
let accessoryType;
|
|
168
|
+
const uuid = this.api.hap.uuid.generate(device.deviceId);
|
|
169
|
+
const existingAccessory = this.accessories.get(uuid);
|
|
170
|
+
// for existing accessories restore from cache
|
|
171
|
+
if (existingAccessory) {
|
|
172
|
+
this.log.info('Restoring existing accessory from cache:', existingAccessory.displayName);
|
|
173
|
+
accessoryType = existingAccessory;
|
|
174
|
+
existingAccessory.context.device = device;
|
|
175
|
+
this.api.updatePlatformAccessories([existingAccessory]);
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
// create new accessory
|
|
179
|
+
this.log.info('Adding new accessory:', device.nickname);
|
|
180
|
+
const accessory = new this.api.platformAccessory(device.nickname, uuid);
|
|
181
|
+
accessoryType = accessory;
|
|
182
|
+
accessory.context.device = device;
|
|
183
|
+
this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory]);
|
|
184
|
+
}
|
|
185
|
+
this.discoveredCacheUUIDs.push(uuid);
|
|
186
|
+
// Setup services based on device type when there are multiple device types in account
|
|
187
|
+
// add more case statements e.g. Washer, Dryer, Oven, etc.
|
|
188
|
+
switch (device.nickname) {
|
|
189
|
+
case 'Refrigerator':
|
|
190
|
+
this.debug('green', `Setting up Refrigerator services for ${device.nickname}`);
|
|
191
|
+
setupRefrigeratorServices.call(this, accessoryType, device, deviceServices);
|
|
192
|
+
break;
|
|
193
|
+
case 'someNewAppliance':
|
|
194
|
+
this.debug('green', `Logic not implemented for ${device.nickname}`);
|
|
195
|
+
break;
|
|
196
|
+
default:
|
|
197
|
+
this.debug('red', `not implemented device : for device ${device.nickname}`);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
// remove accessories from the cache which are no longer present
|
|
201
|
+
for (const [uuid, accessory] of this.accessories) {
|
|
202
|
+
if (!this.discoveredCacheUUIDs.includes(uuid)) {
|
|
203
|
+
this.log.info('Removing existing accessory from cache:', accessory.displayName);
|
|
204
|
+
this.api.unregisterPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory]);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
debug(color, message) {
|
|
209
|
+
if (this.config.debugLogging) {
|
|
210
|
+
switch (color) {
|
|
211
|
+
case 'red':
|
|
212
|
+
this.log.info(chalk.red('[Smarthq] ' + message));
|
|
213
|
+
break;
|
|
214
|
+
case 'blue':
|
|
215
|
+
this.log.info(chalk.blue('[Smarthq] ' + message));
|
|
216
|
+
break;
|
|
217
|
+
case 'green':
|
|
218
|
+
this.log.info(chalk.green('[Smarthq] ' + message));
|
|
219
|
+
break;
|
|
220
|
+
case 'yellow':
|
|
221
|
+
this.log.info(chalk.yellow('[Smarthq] ' + message));
|
|
222
|
+
break;
|
|
223
|
+
default:
|
|
224
|
+
this.log.info('[Smarthq] ' + message);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
// Some models may not have all services available so don't add service if not supported
|
|
232
|
+
deviceSupportsThisService(deviceServices, serviceDeviceType, serviceType, domainType) {
|
|
233
|
+
for (const service of deviceServices) {
|
|
234
|
+
if (service.serviceDeviceType === serviceDeviceType
|
|
235
|
+
&& service.serviceType === serviceType
|
|
236
|
+
&& service.domainType === domainType) {
|
|
237
|
+
return true;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return false;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
//# 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,19 @@
|
|
|
1
|
+
import { CharacteristicValue, PlatformAccessory } from 'homebridge';
|
|
2
|
+
import { SmartHqPlatform } from '../platform.js';
|
|
3
|
+
import { DevService } from '../smarthq-types.js';
|
|
4
|
+
/**
|
|
5
|
+
* Platform Accessory
|
|
6
|
+
* An instance of this class is created for each accessory your platform registers
|
|
7
|
+
* Each accessory may expose multiple services of different service types.
|
|
8
|
+
*/
|
|
9
|
+
export declare class ControlLock {
|
|
10
|
+
private readonly platform;
|
|
11
|
+
private readonly accessory;
|
|
12
|
+
readonly deviceServices: DevService[];
|
|
13
|
+
readonly deviceId: string;
|
|
14
|
+
private readonly smartHqApi;
|
|
15
|
+
private log;
|
|
16
|
+
constructor(platform: SmartHqPlatform, accessory: PlatformAccessory, deviceServices: DevService[], deviceId: string);
|
|
17
|
+
getcontrolsLock(): Promise<CharacteristicValue>;
|
|
18
|
+
setcontrolsLock(value: CharacteristicValue): Promise<void>;
|
|
19
|
+
}
|