homebridge-carrier-infinity 1.8.1 → 1.9.0-beta.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/.devcontainer/.uix-hb-service-homebridge-startup.json.example +5 -0
- package/.devcontainer/config.json.example +2 -1
- package/.devcontainer/setup-homebridge.sh +6 -0
- package/CLAUDE.md +28 -21
- package/dist/accessory_base.d.ts +2 -2
- package/dist/accessory_base.d.ts.map +1 -1
- package/dist/accessory_base.js.map +1 -1
- package/dist/api/graphql_client.d.ts +71 -0
- package/dist/api/graphql_client.d.ts.map +1 -0
- package/dist/api/graphql_client.js +261 -0
- package/dist/api/graphql_client.js.map +1 -0
- package/dist/api/graphql_operations.d.ts +56 -0
- package/dist/api/graphql_operations.d.ts.map +1 -0
- package/dist/api/graphql_operations.js +325 -0
- package/dist/api/graphql_operations.js.map +1 -0
- package/dist/api/interface_graphql_mutations.d.ts +149 -0
- package/dist/api/interface_graphql_mutations.d.ts.map +1 -0
- package/dist/api/interface_graphql_mutations.js +8 -0
- package/dist/api/interface_graphql_mutations.js.map +1 -0
- package/dist/api/interface_graphql_system.d.ts +287 -0
- package/dist/api/interface_graphql_system.d.ts.map +1 -0
- package/dist/api/interface_graphql_system.js +9 -0
- package/dist/api/interface_graphql_system.js.map +1 -0
- package/dist/api/models_graphql.d.ts +167 -0
- package/dist/api/models_graphql.d.ts.map +1 -0
- package/dist/api/models_graphql.js +590 -0
- package/dist/api/models_graphql.js.map +1 -0
- package/dist/api/oauth2.d.ts +45 -0
- package/dist/api/oauth2.d.ts.map +1 -0
- package/dist/api/oauth2.js +35 -0
- package/dist/api/oauth2.js.map +1 -0
- package/dist/characteristics_base.d.ts +2 -2
- package/dist/characteristics_base.d.ts.map +1 -1
- package/dist/characteristics_base.js.map +1 -1
- package/dist/platform.d.ts +4 -4
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +7 -12
- package/dist/platform.js.map +1 -1
- package/dist/settings.d.ts +6 -3
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js +7 -4
- package/dist/settings.js.map +1 -1
- package/eslint.config.mjs +93 -2
- package/package.json +3 -6
- package/dist/api/comodo-aaa-root.pem +0 -25
- package/dist/api/interface_config.d.ts +0 -185
- package/dist/api/interface_config.d.ts.map +0 -1
- package/dist/api/interface_config.js +0 -5
- package/dist/api/interface_config.js.map +0 -1
- package/dist/api/interface_locations.d.ts +0 -45
- package/dist/api/interface_locations.d.ts.map +0 -1
- package/dist/api/interface_locations.js +0 -5
- package/dist/api/interface_locations.js.map +0 -1
- package/dist/api/interface_profile.d.ts +0 -80
- package/dist/api/interface_profile.d.ts.map +0 -1
- package/dist/api/interface_profile.js +0 -5
- package/dist/api/interface_profile.js.map +0 -1
- package/dist/api/interface_status.d.ts +0 -90
- package/dist/api/interface_status.d.ts.map +0 -1
- package/dist/api/interface_status.js +0 -5
- package/dist/api/interface_status.js.map +0 -1
- package/dist/api/models.d.ts +0 -111
- package/dist/api/models.d.ts.map +0 -1
- package/dist/api/models.js +0 -572
- package/dist/api/models.js.map +0 -1
- package/dist/api/oauth.d.ts +0 -6
- package/dist/api/oauth.d.ts.map +0 -1
- package/dist/api/oauth.js +0 -49
- package/dist/api/oauth.js.map +0 -1
- package/dist/api/rest_client.d.ts +0 -15
- package/dist/api/rest_client.d.ts.map +0 -1
- package/dist/api/rest_client.js +0 -135
- package/dist/api/rest_client.js.map +0 -1
|
@@ -17,6 +17,12 @@ if [ ! -f ~/.homebridge/config.json ]; then
|
|
|
17
17
|
cp .devcontainer/config.json.example ~/.homebridge/config.json
|
|
18
18
|
fi
|
|
19
19
|
|
|
20
|
+
# Create debug mode config if it doesn't exist
|
|
21
|
+
if [ ! -f ~/.homebridge/.uix-hb-service-homebridge-startup.json ]; then
|
|
22
|
+
echo "Creating Homebridge service config from example..."
|
|
23
|
+
cp .devcontainer/.uix-hb-service-homebridge-startup.json.example ~/.homebridge/.uix-hb-service-homebridge-startup.json
|
|
24
|
+
fi
|
|
25
|
+
|
|
20
26
|
# Install project dependencies
|
|
21
27
|
echo "Installing project dependencies..."
|
|
22
28
|
npm install
|
package/CLAUDE.md
CHANGED
|
@@ -37,7 +37,8 @@ This repository includes a complete devcontainer configuration that automaticall
|
|
|
37
37
|
When the codespace is created, the setup script (`.devcontainer/setup-homebridge.sh`) automatically:
|
|
38
38
|
- Installs Homebridge, Homebridge Config UI X, and pm2 globally
|
|
39
39
|
- Creates `~/.homebridge/` directory structure
|
|
40
|
-
- Copies `.devcontainer/config.json.example` to `~/.homebridge/config.json`
|
|
40
|
+
- Copies `.devcontainer/config.json.example` to `~/.homebridge/config.json` (Fahrenheit display)
|
|
41
|
+
- Copies `.devcontainer/.uix-hb-service-homebridge-startup.json.example` (debug mode enabled)
|
|
41
42
|
- Installs project dependencies
|
|
42
43
|
- Builds the plugin
|
|
43
44
|
- Symlinks the plugin to `~/.homebridge/node_modules/`
|
|
@@ -75,29 +76,33 @@ The plugin registers itself in [src/index.ts](src/index.ts) and implements the H
|
|
|
75
76
|
|
|
76
77
|
#### 1. Platform ([src/platform.ts](src/platform.ts))
|
|
77
78
|
- Entry point that discovers systems and zones after Homebridge launches
|
|
78
|
-
- Maintains `infinity_client` (
|
|
79
|
-
- Periodically activates the API every 30 minutes to maintain connection
|
|
79
|
+
- Maintains `infinity_client` (GraphQL API client) and `systems` (indexed by serial number)
|
|
80
80
|
- Creates accessories based on config options (outdoor temp sensor, humidity sensors, etc.)
|
|
81
81
|
|
|
82
82
|
#### 2. API Layer ([src/api/](src/api/))
|
|
83
|
-
- **
|
|
84
|
-
- Handles authentication with username/password
|
|
85
|
-
- Automatic
|
|
86
|
-
- Token refresh with 24hr memoization
|
|
87
|
-
-
|
|
88
|
-
|
|
89
|
-
- **
|
|
83
|
+
- **InfinityGraphQLClient** ([src/api/graphql_client.ts](src/api/graphql_client.ts)): OAuth 2.0 authenticated GraphQL client
|
|
84
|
+
- Handles authentication via Okta with username/password
|
|
85
|
+
- Automatic Bearer token injection via interceptor
|
|
86
|
+
- Token refresh with 24hr memoization (via Okta or assistedLogin mutation)
|
|
87
|
+
- No activation endpoint needed (simplified from old REST API)
|
|
88
|
+
|
|
89
|
+
- **GraphQL Operations** ([src/api/graphql_operations.ts](src/api/graphql_operations.ts)): GraphQL queries and mutations
|
|
90
|
+
- `GET_INFINITY_SYSTEMS`: Single query fetches profile, status, and config together (replaces 3 REST calls)
|
|
91
|
+
- `UPDATE_INFINITY_CONFIG`: System-level configuration mutations
|
|
92
|
+
- `UPDATE_INFINITY_ZONE_ACTIVITY`: Zone activity and setpoint mutations
|
|
93
|
+
- `UPDATE_INFINITY_ZONE_CONFIG`: Zone hold and schedule mutations
|
|
94
|
+
|
|
95
|
+
- **Models** ([src/api/models_graphql.ts](src/api/models_graphql.ts)): GraphQL-based models with facade pattern
|
|
96
|
+
- `UnifiedSystemModel` fetches all data (profile + status + config) via single GraphQL query
|
|
97
|
+
- `SystemProfileModel`, `SystemStatusModel`, `SystemConfigModel` are facades that maintain backward compatibility
|
|
90
98
|
- `BaseModel` provides fetch/push pattern with mutex locking to prevent race conditions
|
|
91
99
|
- Hash-based change detection (only pushes if data actually changed)
|
|
92
100
|
- 10-second memoization on fetch operations
|
|
93
|
-
-
|
|
94
|
-
- Models include: `LocationsModel`, `SystemModel` with nested `ConfigModel`, `ProfileModel`, `StatusModel`
|
|
101
|
+
- JSON parsing (native JavaScript objects)
|
|
95
102
|
|
|
96
|
-
- **Interface Files**: TypeScript interfaces
|
|
97
|
-
- [src/api/
|
|
98
|
-
- [src/api/
|
|
99
|
-
- [src/api/interface_status.ts](src/api/interface_status.ts)
|
|
100
|
-
- [src/api/interface_locations.ts](src/api/interface_locations.ts)
|
|
103
|
+
- **Interface Files**: TypeScript interfaces for GraphQL API responses
|
|
104
|
+
- [src/api/interface_graphql_system.ts](src/api/interface_graphql_system.ts): System, profile, status, and config types
|
|
105
|
+
- [src/api/interface_graphql_mutations.ts](src/api/interface_graphql_mutations.ts): Mutation input and response types
|
|
101
106
|
|
|
102
107
|
#### 3. Accessories ([src/accessory_*.ts](src/))
|
|
103
108
|
All accessories extend `BaseAccessory` ([src/accessory_base.ts](src/accessory_base.ts)):
|
|
@@ -127,7 +132,7 @@ The plugin uses a wrapper pattern to bind HomeKit characteristics to API data:
|
|
|
127
132
|
### Key Patterns
|
|
128
133
|
|
|
129
134
|
#### OAuth Authentication
|
|
130
|
-
The API uses OAuth
|
|
135
|
+
The API uses OAuth 2.0 via Okta with Bearer tokens. See [src/api/oauth2.ts](src/api/oauth2.ts) for token injection and [src/settings.ts](src/settings.ts) for OAuth endpoints and client ID. Authentication is handled via the `assistedLogin` GraphQL mutation or Okta token refresh endpoint.
|
|
131
136
|
|
|
132
137
|
#### Memoization & Retry Decorators
|
|
133
138
|
- `@MemoizeExpiring(milliseconds)`: Caches method results for specified duration
|
|
@@ -143,10 +148,12 @@ await tryAcquire(this.write_lock).runExclusive(async () => {
|
|
|
143
148
|
```
|
|
144
149
|
|
|
145
150
|
#### Data Flow
|
|
146
|
-
1. **Read**: Characteristic getter → Model.fetch() →
|
|
147
|
-
2. **Write**: Characteristic setter → batch changes → Model.push() →
|
|
151
|
+
1. **Read**: Characteristic getter → Model.fetch() → GraphQL query → JSON parse → return value
|
|
152
|
+
2. **Write**: Characteristic setter → batch changes → Model.push() → GraphQL mutation → JSON input
|
|
148
153
|
3. **Updates**: Periodic polling + hash comparison triggers characteristic updates via subscription pattern
|
|
149
154
|
|
|
155
|
+
**Note**: The GraphQL API combines profile, status, and config data in a single query, reducing network overhead by 66% compared to the old REST API (1 query vs 3 separate calls).
|
|
156
|
+
|
|
150
157
|
#### Hold Behavior
|
|
151
158
|
The plugin supports multiple thermostat hold modes (forever, until next activity, for X hours, until time X) configured via `holdBehavior` and `holdArgument` in config.
|
|
152
159
|
|
|
@@ -173,7 +180,7 @@ The plugin supports multiple thermostat hold modes (forever, until next activity
|
|
|
173
180
|
|
|
174
181
|
## Important Notes
|
|
175
182
|
|
|
176
|
-
- The API expects `activate()` calls regularly (~1 min), though more frequent doesn't help
|
|
177
183
|
- Changes from HomeKit can take 1-2 minutes to reach the physical thermostat due to polling architecture
|
|
178
184
|
- Node version requirement: >= 18
|
|
179
185
|
- Homebridge version: >= 1.2 or ^2.0.0-beta.0
|
|
186
|
+
- The plugin uses the new GraphQL API (OAuth 2.0, JSON) which replaced the old REST API (OAuth 1.0, XML)
|
package/dist/accessory_base.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { Logger, PlatformAccessory, Service, WithUUID } from 'homebridge';
|
|
2
|
-
import {
|
|
2
|
+
import { SystemModelGraphQL } from './api/models_graphql';
|
|
3
3
|
import { CarrierInfinityHomebridgePlatform } from './platform';
|
|
4
4
|
export declare abstract class BaseAccessory {
|
|
5
5
|
protected readonly platform: CarrierInfinityHomebridgePlatform;
|
|
6
6
|
protected readonly context: Record<string, string>;
|
|
7
7
|
readonly accessory: PlatformAccessory;
|
|
8
|
-
protected readonly system:
|
|
8
|
+
protected readonly system: SystemModelGraphQL;
|
|
9
9
|
protected readonly log: Logger;
|
|
10
10
|
constructor(platform: CarrierInfinityHomebridgePlatform, context: Record<string, string>);
|
|
11
11
|
protected abstract ID(context: Record<string, string>): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"accessory_base.d.ts","sourceRoot":"","sources":["../src/accessory_base.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE1E,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"accessory_base.d.ts","sourceRoot":"","sources":["../src/accessory_base.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE1E,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,iCAAiC,EAAE,MAAM,YAAY,CAAC;AAG/D,8BAAsB,aAAa;IAM/B,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,iCAAiC;IAC9D,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IANpD,SAAgB,SAAS,EAAE,iBAAiB,CAAC;IAC7C,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAoD;IACjG,SAAS,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAwD;gBAGjE,QAAQ,EAAE,iCAAiC,EAC3C,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAkBpD,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM;IAE9D,SAAS,CAAC,UAAU,CAAC,IAAI,EAAE,QAAQ,CAAC,OAAO,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO;CAW9F"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"accessory_base.js","sourceRoot":"","sources":["../src/accessory_base.ts"],"names":[],"mappings":";;;AACA,qDAAgD;AAGhD,yCAAwD;AAExD,MAAsB,aAAa;IAKjC,YACqB,QAA2C,EAC3C,OAA+B;QAD/B,aAAQ,GAAR,QAAQ,CAAmC;QAC3C,YAAO,GAAP,OAAO,CAAwB;QALjC,WAAM,
|
|
1
|
+
{"version":3,"file":"accessory_base.js","sourceRoot":"","sources":["../src/accessory_base.ts"],"names":[],"mappings":";;;AACA,qDAAgD;AAGhD,yCAAwD;AAExD,MAAsB,aAAa;IAKjC,YACqB,QAA2C,EAC3C,OAA+B;QAD/B,aAAQ,GAAR,QAAQ,CAAmC;QAC3C,YAAO,GAAP,OAAO,CAAwB;QALjC,WAAM,GAAuB,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QAC9E,QAAG,GAAW,IAAI,6BAAY,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAMpF,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;QACnE,IAAI,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC;QACzD,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACvB,SAAS,GAAG,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,iBAAiB,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YACxE,SAAS,CAAC,OAAO,GAAG,OAAO,CAAC;YAC5B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,2BAA2B,CAAC,sBAAW,EAAE,wBAAa,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC;QACzF,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACxB,SAAS,CAAC,OAAO,GAAG,OAAO,CAAC;YAC5B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;QAC3D,CAAC;QACD,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IACzC,CAAC;IAIS,UAAU,CAAC,IAA8B,EAAE,IAAY,EAAE,QAAgB;QACjF,+BAA+B;QAC/B,IAAI,OAA4B,CAAC;QACjC,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAC1D,CAAC;aAAM,CAAC;YACN,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAC5C,CAAC;QACD,2BAA2B;QAC3B,OAAO,OAAO,IAAI,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;IACpE,CAAC;CACF;AAtCD,sCAsCC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GraphQL Client for Carrier Infinity API
|
|
3
|
+
*
|
|
4
|
+
* This replaces the InfinityRestClient with a GraphQL-based implementation
|
|
5
|
+
* using OAuth 2.0 Bearer token authentication instead of OAuth 1.0 HMAC signatures.
|
|
6
|
+
*/
|
|
7
|
+
import { AxiosInstance } from 'axios';
|
|
8
|
+
import { Logger } from 'homebridge';
|
|
9
|
+
/**
|
|
10
|
+
* GraphQL Client for Carrier Infinity API
|
|
11
|
+
*
|
|
12
|
+
* Handles OAuth 2.0 authentication and GraphQL query/mutation execution.
|
|
13
|
+
* Much simpler than the old REST client - no XML parsing, no OAuth signatures,
|
|
14
|
+
* no custom certificates, no activation endpoint.
|
|
15
|
+
*/
|
|
16
|
+
export declare class InfinityGraphQLClient {
|
|
17
|
+
username: string;
|
|
18
|
+
private password;
|
|
19
|
+
readonly log: Logger;
|
|
20
|
+
private access_token;
|
|
21
|
+
private refresh_token;
|
|
22
|
+
private token_type;
|
|
23
|
+
private token_expires_in;
|
|
24
|
+
private token_acquired_at;
|
|
25
|
+
axios: AxiosInstance;
|
|
26
|
+
private axiosNoAuth;
|
|
27
|
+
constructor(username: string, password: string, log: Logger);
|
|
28
|
+
/**
|
|
29
|
+
* Refresh OAuth 2.0 token with memoization (24 hours)
|
|
30
|
+
*
|
|
31
|
+
* This is called before every API request to ensure we have a valid token.
|
|
32
|
+
* The memoization ensures we only refresh once per day unless the token expires.
|
|
33
|
+
*/
|
|
34
|
+
refreshToken(): Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* Force refresh OAuth 2.0 token with retry logic
|
|
37
|
+
*
|
|
38
|
+
* If we have a refresh token, use the Okta token endpoint.
|
|
39
|
+
* Otherwise, use the assistedLogin mutation to get a new token.
|
|
40
|
+
*/
|
|
41
|
+
forceRefreshToken(): Promise<void>;
|
|
42
|
+
/**
|
|
43
|
+
* Refresh token via Okta OAuth2 endpoint
|
|
44
|
+
*/
|
|
45
|
+
private refreshTokenViaOkta;
|
|
46
|
+
/**
|
|
47
|
+
* Login via assistedLogin GraphQL mutation
|
|
48
|
+
*/
|
|
49
|
+
private loginViaAssistedLogin;
|
|
50
|
+
/**
|
|
51
|
+
* Execute a GraphQL query
|
|
52
|
+
*
|
|
53
|
+
* @param query - GraphQL query string
|
|
54
|
+
* @param variables - Query variables
|
|
55
|
+
* @returns GraphQL response data
|
|
56
|
+
*/
|
|
57
|
+
query<T>(query: string, variables?: Record<string, unknown>): Promise<T>;
|
|
58
|
+
/**
|
|
59
|
+
* Execute a GraphQL mutation
|
|
60
|
+
*
|
|
61
|
+
* @param mutation - GraphQL mutation string
|
|
62
|
+
* @param variables - Mutation variables
|
|
63
|
+
* @returns GraphQL response data
|
|
64
|
+
*/
|
|
65
|
+
mutate<T>(mutation: string, variables?: Record<string, unknown>): Promise<T>;
|
|
66
|
+
/**
|
|
67
|
+
* Helper to check if GraphQL response has errors
|
|
68
|
+
*/
|
|
69
|
+
private hasGraphQLErrors;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=graphql_client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graphql_client.d.ts","sourceRoot":"","sources":["../../src/api/graphql_client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAiBH,OAAc,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAIpC;;;;;;GAMG;AACH,qBAAa,qBAAqB;IAWvB,QAAQ,EAAE,MAAM;IACvB,OAAO,CAAC,QAAQ;aACA,GAAG,EAAE,MAAM;IAZ7B,OAAO,CAAC,YAAY,CAAM;IAC1B,OAAO,CAAC,aAAa,CAAM;IAC3B,OAAO,CAAC,UAAU,CAAY;IAC9B,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,iBAAiB,CAAK;IAEvB,KAAK,EAAE,aAAa,CAAC;IAC5B,OAAO,CAAC,WAAW,CAAgB;gBAG1B,QAAQ,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EACR,GAAG,EAAE,MAAM;IAkE7B;;;;;OAKG;IAEG,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAanC;;;;;OAKG;IAOG,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;IAuBxC;;OAEG;YACW,mBAAmB;IAiCjC;;OAEG;YACW,qBAAqB;IAuCnC;;;;;;OAMG;IACG,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAsB9E;;;;;;OAMG;IACG,MAAM,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAsBlF;;OAEG;IACH,OAAO,CAAC,gBAAgB;CAGzB"}
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* GraphQL Client for Carrier Infinity API
|
|
4
|
+
*
|
|
5
|
+
* This replaces the InfinityRestClient with a GraphQL-based implementation
|
|
6
|
+
* using OAuth 2.0 Bearer token authentication instead of OAuth 1.0 HMAC signatures.
|
|
7
|
+
*/
|
|
8
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
9
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
10
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
11
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
12
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
13
|
+
};
|
|
14
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
15
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
16
|
+
};
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.InfinityGraphQLClient = void 0;
|
|
19
|
+
const settings_1 = require("../settings");
|
|
20
|
+
const oauth2_1 = require("./oauth2");
|
|
21
|
+
const graphql_operations_1 = require("./graphql_operations");
|
|
22
|
+
const axios_1 = __importDefault(require("axios"));
|
|
23
|
+
const typescript_memoize_1 = require("typescript-memoize");
|
|
24
|
+
const typescript_retry_decorator_1 = require("typescript-retry-decorator");
|
|
25
|
+
/**
|
|
26
|
+
* GraphQL Client for Carrier Infinity API
|
|
27
|
+
*
|
|
28
|
+
* Handles OAuth 2.0 authentication and GraphQL query/mutation execution.
|
|
29
|
+
* Much simpler than the old REST client - no XML parsing, no OAuth signatures,
|
|
30
|
+
* no custom certificates, no activation endpoint.
|
|
31
|
+
*/
|
|
32
|
+
class InfinityGraphQLClient {
|
|
33
|
+
constructor(username, password, log) {
|
|
34
|
+
this.username = username;
|
|
35
|
+
this.password = password;
|
|
36
|
+
this.log = log;
|
|
37
|
+
this.access_token = '';
|
|
38
|
+
this.refresh_token = '';
|
|
39
|
+
this.token_type = 'Bearer';
|
|
40
|
+
this.token_expires_in = 0;
|
|
41
|
+
this.token_acquired_at = 0;
|
|
42
|
+
// Create authenticated Axios instance (for GraphQL queries after login)
|
|
43
|
+
this.axios = axios_1.default.create({
|
|
44
|
+
baseURL: settings_1.INFINITY_GRAPHQL_ENDPOINT,
|
|
45
|
+
headers: {
|
|
46
|
+
'Content-Type': 'application/json',
|
|
47
|
+
Accept: 'application/json',
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
// Create no-auth Axios instance (for login mutation)
|
|
51
|
+
this.axiosNoAuth = axios_1.default.create({
|
|
52
|
+
baseURL: settings_1.INFINITY_GRAPHQL_NO_AUTH_ENDPOINT,
|
|
53
|
+
headers: {
|
|
54
|
+
'Content-Type': 'application/json',
|
|
55
|
+
Accept: 'application/json',
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
// Response interceptor for debug logging
|
|
59
|
+
this.axios.interceptors.response.use(response => {
|
|
60
|
+
var _a, _b;
|
|
61
|
+
this.log.debug(`[GraphQL] ${(_a = response.request) === null || _a === void 0 ? void 0 : _a.method} ${response.request.host}${(_b = response.request) === null || _b === void 0 ? void 0 : _b.path}`, `${response.status} ${response.statusText}`);
|
|
62
|
+
return response;
|
|
63
|
+
}, error => {
|
|
64
|
+
var _a, _b, _c, _d, _e;
|
|
65
|
+
if (axios_1.default.isAxiosError(error)) {
|
|
66
|
+
this.log.debug(`[GraphQL] ${(_a = error.request) === null || _a === void 0 ? void 0 : _a.method} ${(_b = error.request) === null || _b === void 0 ? void 0 : _b.host}${(_c = error.request) === null || _c === void 0 ? void 0 : _c.path}`, `${(_d = error.response) === null || _d === void 0 ? void 0 : _d.status} ${(_e = error.response) === null || _e === void 0 ? void 0 : _e.statusText}`);
|
|
67
|
+
}
|
|
68
|
+
return Promise.reject(error);
|
|
69
|
+
});
|
|
70
|
+
// Same for no-auth instance
|
|
71
|
+
this.axiosNoAuth.interceptors.response.use(response => {
|
|
72
|
+
var _a, _b;
|
|
73
|
+
this.log.debug(`[GraphQL-NoAuth] ${(_a = response.request) === null || _a === void 0 ? void 0 : _a.method} ${response.request.host}${(_b = response.request) === null || _b === void 0 ? void 0 : _b.path}`, `${response.status} ${response.statusText}`);
|
|
74
|
+
return response;
|
|
75
|
+
}, error => {
|
|
76
|
+
var _a, _b, _c, _d, _e;
|
|
77
|
+
if (axios_1.default.isAxiosError(error)) {
|
|
78
|
+
this.log.debug(`[GraphQL-NoAuth] ${(_a = error.request) === null || _a === void 0 ? void 0 : _a.method} ${(_b = error.request) === null || _b === void 0 ? void 0 : _b.host}${(_c = error.request) === null || _c === void 0 ? void 0 : _c.path}`, `${(_d = error.response) === null || _d === void 0 ? void 0 : _d.status} ${(_e = error.response) === null || _e === void 0 ? void 0 : _e.statusText}`);
|
|
79
|
+
}
|
|
80
|
+
return Promise.reject(error);
|
|
81
|
+
});
|
|
82
|
+
// OAuth 2.0 Bearer token injection for authenticated instance
|
|
83
|
+
this.axios.interceptors.request.use(config => {
|
|
84
|
+
return oauth2_1.OAuth2Headers.intercept(config, this.access_token, this.token_type);
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Refresh OAuth 2.0 token with memoization (24 hours)
|
|
89
|
+
*
|
|
90
|
+
* This is called before every API request to ensure we have a valid token.
|
|
91
|
+
* The memoization ensures we only refresh once per day unless the token expires.
|
|
92
|
+
*/
|
|
93
|
+
async refreshToken() {
|
|
94
|
+
try {
|
|
95
|
+
await this.forceRefreshToken();
|
|
96
|
+
this.log.info('Completed login / token refresh successfully.');
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
this.log.error('[API] Could not refresh access token: ', axios_1.default.isAxiosError(error) ? error.message : error);
|
|
100
|
+
throw error;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Force refresh OAuth 2.0 token with retry logic
|
|
105
|
+
*
|
|
106
|
+
* If we have a refresh token, use the Okta token endpoint.
|
|
107
|
+
* Otherwise, use the assistedLogin mutation to get a new token.
|
|
108
|
+
*/
|
|
109
|
+
async forceRefreshToken() {
|
|
110
|
+
this.log.info('Attempting login / token refresh.');
|
|
111
|
+
// Check if we can use refresh token
|
|
112
|
+
const now = Date.now() / 1000;
|
|
113
|
+
const tokenAge = now - this.token_acquired_at;
|
|
114
|
+
const tokenExpired = tokenAge >= this.token_expires_in;
|
|
115
|
+
if (this.refresh_token && !tokenExpired) {
|
|
116
|
+
// Use Okta refresh token endpoint
|
|
117
|
+
try {
|
|
118
|
+
await this.refreshTokenViaOkta();
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
this.log.warn('Okta token refresh failed, falling back to assistedLogin:', error);
|
|
123
|
+
// Fall through to assistedLogin
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// Use assistedLogin mutation
|
|
127
|
+
await this.loginViaAssistedLogin();
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Refresh token via Okta OAuth2 endpoint
|
|
131
|
+
*/
|
|
132
|
+
async refreshTokenViaOkta() {
|
|
133
|
+
const response = await axios_1.default.post(settings_1.INFINITY_OAUTH_TOKEN_ENDPOINT, {
|
|
134
|
+
client_id: settings_1.INFINITY_OAUTH_CLIENT_ID,
|
|
135
|
+
grant_type: 'refresh_token',
|
|
136
|
+
refresh_token: this.refresh_token,
|
|
137
|
+
scope: 'offline_access',
|
|
138
|
+
}, {
|
|
139
|
+
headers: {
|
|
140
|
+
'Content-Type': 'application/json',
|
|
141
|
+
},
|
|
142
|
+
});
|
|
143
|
+
if (response.data.access_token) {
|
|
144
|
+
this.access_token = response.data.access_token;
|
|
145
|
+
this.token_type = response.data.token_type;
|
|
146
|
+
this.token_expires_in = response.data.expires_in;
|
|
147
|
+
this.token_acquired_at = Date.now() / 1000;
|
|
148
|
+
// Okta may return a new refresh token
|
|
149
|
+
if (response.data.refresh_token) {
|
|
150
|
+
this.refresh_token = response.data.refresh_token;
|
|
151
|
+
}
|
|
152
|
+
this.log.debug('Token refreshed via Okta endpoint.');
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
throw new Error('Okta token refresh did not return access_token.');
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Login via assistedLogin GraphQL mutation
|
|
160
|
+
*/
|
|
161
|
+
async loginViaAssistedLogin() {
|
|
162
|
+
var _a;
|
|
163
|
+
const input = {
|
|
164
|
+
username: this.username,
|
|
165
|
+
password: this.password,
|
|
166
|
+
};
|
|
167
|
+
const response = await this.axiosNoAuth.post('', {
|
|
168
|
+
query: graphql_operations_1.ASSISTED_LOGIN,
|
|
169
|
+
variables: { input },
|
|
170
|
+
});
|
|
171
|
+
// Check for GraphQL errors
|
|
172
|
+
if (response.data.errors && response.data.errors.length > 0) {
|
|
173
|
+
const errorMessages = response.data.errors.map(e => e.message).join(', ');
|
|
174
|
+
throw new Error(`GraphQL errors during login: ${errorMessages}`);
|
|
175
|
+
}
|
|
176
|
+
// Check for mutation-level errors
|
|
177
|
+
const result = (_a = response.data.data) === null || _a === void 0 ? void 0 : _a.assistedLogin;
|
|
178
|
+
if (!result || !result.success) {
|
|
179
|
+
const errorMessage = (result === null || result === void 0 ? void 0 : result.errorMessage) || 'Unknown error';
|
|
180
|
+
throw new Error(`assistedLogin failed: ${errorMessage}`);
|
|
181
|
+
}
|
|
182
|
+
// Extract tokens
|
|
183
|
+
const tokenData = result.data;
|
|
184
|
+
if (!tokenData.access_token) {
|
|
185
|
+
throw new Error('assistedLogin did not return access_token.');
|
|
186
|
+
}
|
|
187
|
+
this.access_token = tokenData.access_token;
|
|
188
|
+
this.refresh_token = tokenData.refresh_token;
|
|
189
|
+
this.token_type = tokenData.token_type;
|
|
190
|
+
this.token_expires_in = tokenData.expires_in;
|
|
191
|
+
this.token_acquired_at = Date.now() / 1000;
|
|
192
|
+
this.log.debug('Token acquired via assistedLogin mutation.');
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Execute a GraphQL query
|
|
196
|
+
*
|
|
197
|
+
* @param query - GraphQL query string
|
|
198
|
+
* @param variables - Query variables
|
|
199
|
+
* @returns GraphQL response data
|
|
200
|
+
*/
|
|
201
|
+
async query(query, variables) {
|
|
202
|
+
// Ensure we have a valid token
|
|
203
|
+
await this.refreshToken();
|
|
204
|
+
const response = await this.axios.post('', {
|
|
205
|
+
query,
|
|
206
|
+
variables,
|
|
207
|
+
});
|
|
208
|
+
// Check for GraphQL errors
|
|
209
|
+
if (response.data.errors && response.data.errors.length > 0) {
|
|
210
|
+
const errorMessages = response.data.errors.map(e => e.message).join(', ');
|
|
211
|
+
throw new Error(`GraphQL query errors: ${errorMessages}`);
|
|
212
|
+
}
|
|
213
|
+
if (!response.data.data) {
|
|
214
|
+
throw new Error('GraphQL query returned no data.');
|
|
215
|
+
}
|
|
216
|
+
return response.data.data;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Execute a GraphQL mutation
|
|
220
|
+
*
|
|
221
|
+
* @param mutation - GraphQL mutation string
|
|
222
|
+
* @param variables - Mutation variables
|
|
223
|
+
* @returns GraphQL response data
|
|
224
|
+
*/
|
|
225
|
+
async mutate(mutation, variables) {
|
|
226
|
+
// Ensure we have a valid token
|
|
227
|
+
await this.refreshToken();
|
|
228
|
+
const response = await this.axios.post('', {
|
|
229
|
+
query: mutation,
|
|
230
|
+
variables,
|
|
231
|
+
});
|
|
232
|
+
// Check for GraphQL errors
|
|
233
|
+
if (response.data.errors && response.data.errors.length > 0) {
|
|
234
|
+
const errorMessages = response.data.errors.map(e => e.message).join(', ');
|
|
235
|
+
throw new Error(`GraphQL mutation errors: ${errorMessages}`);
|
|
236
|
+
}
|
|
237
|
+
if (!response.data.data) {
|
|
238
|
+
throw new Error('GraphQL mutation returned no data.');
|
|
239
|
+
}
|
|
240
|
+
return response.data.data;
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Helper to check if GraphQL response has errors
|
|
244
|
+
*/
|
|
245
|
+
hasGraphQLErrors(errors) {
|
|
246
|
+
return !!(errors && errors.length > 0);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
exports.InfinityGraphQLClient = InfinityGraphQLClient;
|
|
250
|
+
__decorate([
|
|
251
|
+
(0, typescript_memoize_1.MemoizeExpiring)(24 * 60 * 60 * 1000) // every 24 hrs
|
|
252
|
+
], InfinityGraphQLClient.prototype, "refreshToken", null);
|
|
253
|
+
__decorate([
|
|
254
|
+
(0, typescript_retry_decorator_1.Retryable)({
|
|
255
|
+
maxAttempts: 5,
|
|
256
|
+
backOffPolicy: typescript_retry_decorator_1.BackOffPolicy.ExponentialBackOffPolicy,
|
|
257
|
+
backOff: 1000,
|
|
258
|
+
exponentialOption: { maxInterval: 5 * 60 * 1000, multiplier: 5 },
|
|
259
|
+
})
|
|
260
|
+
], InfinityGraphQLClient.prototype, "forceRefreshToken", null);
|
|
261
|
+
//# sourceMappingURL=graphql_client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graphql_client.js","sourceRoot":"","sources":["../../src/api/graphql_client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GraphQL Operations for Carrier Infinity API
|
|
3
|
+
*
|
|
4
|
+
* This file contains all GraphQL queries and mutations used to interact with
|
|
5
|
+
* the Carrier Infinity GraphQL API at dataservice.infinity.iot.carrier.com
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Authentication mutation - used to obtain OAuth tokens
|
|
9
|
+
* Endpoint: https://dataservice.infinity.iot.carrier.com/graphql-no-auth
|
|
10
|
+
* No authentication required (this IS the authentication)
|
|
11
|
+
*/
|
|
12
|
+
export declare const ASSISTED_LOGIN = "\n mutation assistedLogin($input: AssistedLoginInput!) {\n assistedLogin(input: $input) {\n success\n status\n errorMessage\n data {\n token_type\n expires_in\n access_token\n scope\n refresh_token\n }\n }\n }\n";
|
|
13
|
+
/**
|
|
14
|
+
* User information query - fetches user profile and location data
|
|
15
|
+
* Used to discover systems associated with a user account
|
|
16
|
+
*/
|
|
17
|
+
export declare const GET_USER = "\n query getUser($userName: String!, $appVersion: String, $brand: String, $os: String, $osVersion: String) {\n user(\n userName: $userName\n appVersion: $appVersion\n brand: $brand\n os: $os\n osVersion: $osVersion\n ) {\n username\n identityId\n first\n last\n email\n emailVerified\n postal\n locations {\n locationId\n name\n systems {\n config {\n zones {\n id\n enabled\n }\n }\n profile {\n serial\n name\n }\n status {\n isDisconnected\n }\n }\n devices {\n deviceId\n type\n thingName\n name\n connectionStatus\n }\n }\n }\n }\n";
|
|
18
|
+
/**
|
|
19
|
+
* Infinity Systems query - fetches complete system data (profile + status + config)
|
|
20
|
+
* This single query replaces the old REST API's separate profile, status, and config endpoints
|
|
21
|
+
*/
|
|
22
|
+
export declare const GET_INFINITY_SYSTEMS = "\n query getInfinitySystems($userName: String!) {\n infinitySystems(userName: $userName) {\n profile {\n serial\n name\n firmware\n model\n brand\n indoorModel\n indoorSerial\n idutype\n idusource\n outdoorModel\n outdoorSerial\n odutype\n }\n status {\n localTime\n localTimeOffset\n utcTime\n wcTime\n isDisconnected\n cfgem\n mode\n vacatrunning\n oat\n odu {\n type\n opstat\n }\n filtrlvl\n idu {\n type\n opstat\n cfm\n statpress\n blwrpm\n }\n vent\n ventlvl\n humid\n humlvl\n uvlvl\n zones {\n id\n rt\n rh\n fan\n htsp\n clsp\n hold\n enabled\n currentActivity\n zoneconditioning\n }\n }\n config {\n etag\n mode\n cfgem\n cfgdead\n cfgvent\n cfghumid\n cfguv\n cfgfan\n heatsource\n vacat\n vacstart\n vacend\n vacmint\n vacmaxt\n vacfan\n fueltype\n gasunit\n filtertype\n filterinterval\n humidityVacation {\n rclgovercool\n ventspdclg\n ventclg\n rhtg\n humidifier\n humid\n venthtg\n rclg\n ventspdhtg\n }\n zones {\n id\n name\n enabled\n hold\n holdActivity\n otmr\n occEnabled\n program {\n id\n day {\n id\n zoneId\n period {\n id\n zoneId\n dayId\n activity\n time\n enabled\n }\n }\n }\n activities {\n id\n zoneId\n type\n fan\n htsp\n clsp\n }\n }\n humidityAway {\n humid\n humidifier\n rhtg\n rclg\n rclgovercool\n }\n humidityHome {\n humid\n humidifier\n rhtg\n rclg\n rclgovercool\n }\n }\n }\n }\n";
|
|
23
|
+
/**
|
|
24
|
+
* Energy data query - fetches energy usage and efficiency data
|
|
25
|
+
* This is new functionality not available in the old REST API
|
|
26
|
+
*/
|
|
27
|
+
export declare const GET_INFINITY_ENERGY = "\n query getInfinityEnergy($serial: String!) {\n infinityEnergy(serial: $serial) {\n energyConfig {\n cooling {\n display\n enabled\n }\n eheat {\n display\n enabled\n }\n fan {\n display\n enabled\n }\n fangas {\n display\n enabled\n }\n gas {\n display\n enabled\n }\n hpheat {\n display\n enabled\n }\n looppump {\n display\n enabled\n }\n reheat {\n display\n enabled\n }\n hspf\n seer\n }\n energyPeriods {\n energyPeriodType\n eHeatKwh\n coolingKwh\n fanGasKwh\n fanKwh\n hPHeatKwh\n loopPumpKwh\n gasKwh\n reheatKwh\n }\n }\n }\n";
|
|
28
|
+
/**
|
|
29
|
+
* Update system configuration mutation
|
|
30
|
+
* Used for system-level settings like mode, humidity, heat source, etc.
|
|
31
|
+
*
|
|
32
|
+
* Example inputs:
|
|
33
|
+
* - Set mode: { serial, mode: "cool" }
|
|
34
|
+
* - Set humidity: { serial, humidityHome: { humidifier: "on", rhtg: 8 } }
|
|
35
|
+
* - Set heat source: { serial, heatsource: "system" }
|
|
36
|
+
*/
|
|
37
|
+
export declare const UPDATE_INFINITY_CONFIG = "\n mutation updateInfinityConfig($input: InfinityConfigInput!) {\n updateInfinityConfig(input: $input) {\n etag\n }\n }\n";
|
|
38
|
+
/**
|
|
39
|
+
* Update zone activity mutation
|
|
40
|
+
* Used for changing zone activity type, setpoints, and fan mode
|
|
41
|
+
*
|
|
42
|
+
* Example inputs:
|
|
43
|
+
* - Set manual activity: { serial, zoneId, activityType: "manual", clsp: "75", htsp: "68", fan: "med" }
|
|
44
|
+
* - Update fan: { serial, zoneId, activityType: "manual", fan: "high" }
|
|
45
|
+
*/
|
|
46
|
+
export declare const UPDATE_INFINITY_ZONE_ACTIVITY = "\n mutation updateInfinityZoneActivity($input: InfinityZoneActivityInput!) {\n updateInfinityZoneActivity(input: $input) {\n etag\n }\n }\n";
|
|
47
|
+
/**
|
|
48
|
+
* Update zone configuration mutation
|
|
49
|
+
* Used for zone-level settings like hold status, schedule, etc.
|
|
50
|
+
*
|
|
51
|
+
* Example inputs:
|
|
52
|
+
* - Set hold: { serial, zoneId, hold: "on", holdActivity: "manual", otmr: "2024-01-30T18:00:00" }
|
|
53
|
+
* - Cancel hold: { serial, zoneId, hold: "off", holdActivity: null, otmr: null }
|
|
54
|
+
*/
|
|
55
|
+
export declare const UPDATE_INFINITY_ZONE_CONFIG = "\n mutation updateInfinityZoneConfig($input: InfinityZoneConfigInput!) {\n updateInfinityZoneConfig(input: $input) {\n etag\n }\n }\n";
|
|
56
|
+
//# sourceMappingURL=graphql_operations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graphql_operations.d.ts","sourceRoot":"","sources":["../../src/api/graphql_operations.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;GAIG;AACH,eAAO,MAAM,cAAc,4RAe1B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,QAAQ,40BA4CpB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,oBAAoB,q5EAyIhC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,s4BAoD/B,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,sBAAsB,2IAMlC,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,6BAA6B,6JAMzC,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,2BAA2B,uJAMvC,CAAC"}
|