homebridge-smartthings-oauth 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.
Files changed (142) hide show
  1. package/.devcontainer/Dockerfile +16 -0
  2. package/.devcontainer/devcontainer.json +36 -0
  3. package/LICENSE +176 -0
  4. package/README.md +114 -0
  5. package/config.schema.json +134 -0
  6. package/dist/auth/auth.d.ts +23 -0
  7. package/dist/auth/auth.d.ts.map +1 -0
  8. package/dist/auth/auth.js +168 -0
  9. package/dist/auth/auth.js.map +1 -0
  10. package/dist/auth/tokenManager.d.ts +36 -0
  11. package/dist/auth/tokenManager.d.ts.map +1 -0
  12. package/dist/auth/tokenManager.js +180 -0
  13. package/dist/auth/tokenManager.js.map +1 -0
  14. package/dist/basePlatformAccessory.d.ts +49 -0
  15. package/dist/basePlatformAccessory.d.ts.map +1 -0
  16. package/dist/basePlatformAccessory.js +209 -0
  17. package/dist/basePlatformAccessory.js.map +1 -0
  18. package/dist/index.d.ts +7 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +7 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/keyValues.d.ts +4 -0
  23. package/dist/keyValues.d.ts.map +1 -0
  24. package/dist/keyValues.js +12 -0
  25. package/dist/keyValues.js.map +1 -0
  26. package/dist/multiServiceAccessory.d.ts +60 -0
  27. package/dist/multiServiceAccessory.d.ts.map +1 -0
  28. package/dist/multiServiceAccessory.js +398 -0
  29. package/dist/multiServiceAccessory.js.map +1 -0
  30. package/dist/platform.d.ts +42 -0
  31. package/dist/platform.d.ts.map +1 -0
  32. package/dist/platform.js +302 -0
  33. package/dist/platform.js.map +1 -0
  34. package/dist/services/airConditionerService.d.ts +52 -0
  35. package/dist/services/airConditionerService.d.ts.map +1 -0
  36. package/dist/services/airConditionerService.js +438 -0
  37. package/dist/services/airConditionerService.js.map +1 -0
  38. package/dist/services/baseService.d.ts +21 -0
  39. package/dist/services/baseService.d.ts.map +1 -0
  40. package/dist/services/baseService.js +63 -0
  41. package/dist/services/baseService.js.map +1 -0
  42. package/dist/services/batteryService.d.ts +10 -0
  43. package/dist/services/batteryService.d.ts.map +1 -0
  44. package/dist/services/batteryService.js +71 -0
  45. package/dist/services/batteryService.js.map +1 -0
  46. package/dist/services/carbonMonoxideDetector.d.ts +11 -0
  47. package/dist/services/carbonMonoxideDetector.d.ts.map +1 -0
  48. package/dist/services/carbonMonoxideDetector.js +28 -0
  49. package/dist/services/carbonMonoxideDetector.js.map +1 -0
  50. package/dist/services/contactSensorService.d.ts +10 -0
  51. package/dist/services/contactSensorService.d.ts.map +1 -0
  52. package/dist/services/contactSensorService.js +28 -0
  53. package/dist/services/contactSensorService.js.map +1 -0
  54. package/dist/services/doorService.d.ts +16 -0
  55. package/dist/services/doorService.d.ts.map +1 -0
  56. package/dist/services/doorService.js +138 -0
  57. package/dist/services/doorService.js.map +1 -0
  58. package/dist/services/fanSpeedService.d.ts +15 -0
  59. package/dist/services/fanSpeedService.d.ts.map +1 -0
  60. package/dist/services/fanSpeedService.js +153 -0
  61. package/dist/services/fanSpeedService.js.map +1 -0
  62. package/dist/services/fanSwitchLevelService.d.ts +14 -0
  63. package/dist/services/fanSwitchLevelService.d.ts.map +1 -0
  64. package/dist/services/fanSwitchLevelService.js +121 -0
  65. package/dist/services/fanSwitchLevelService.js.map +1 -0
  66. package/dist/services/humidityService.d.ts +10 -0
  67. package/dist/services/humidityService.d.ts.map +1 -0
  68. package/dist/services/humidityService.js +23 -0
  69. package/dist/services/humidityService.js.map +1 -0
  70. package/dist/services/leakDetector.d.ts +10 -0
  71. package/dist/services/leakDetector.d.ts.map +1 -0
  72. package/dist/services/leakDetector.js +27 -0
  73. package/dist/services/leakDetector.js.map +1 -0
  74. package/dist/services/lightSensorService.d.ts +10 -0
  75. package/dist/services/lightSensorService.d.ts.map +1 -0
  76. package/dist/services/lightSensorService.js +24 -0
  77. package/dist/services/lightSensorService.js.map +1 -0
  78. package/dist/services/lightService.d.ts +26 -0
  79. package/dist/services/lightService.d.ts.map +1 -0
  80. package/dist/services/lightService.js +340 -0
  81. package/dist/services/lightService.js.map +1 -0
  82. package/dist/services/lockService.d.ts +16 -0
  83. package/dist/services/lockService.d.ts.map +1 -0
  84. package/dist/services/lockService.js +128 -0
  85. package/dist/services/lockService.js.map +1 -0
  86. package/dist/services/motionService.d.ts +10 -0
  87. package/dist/services/motionService.d.ts.map +1 -0
  88. package/dist/services/motionService.js +23 -0
  89. package/dist/services/motionService.js.map +1 -0
  90. package/dist/services/occupancySensorService.d.ts +10 -0
  91. package/dist/services/occupancySensorService.d.ts.map +1 -0
  92. package/dist/services/occupancySensorService.js +23 -0
  93. package/dist/services/occupancySensorService.js.map +1 -0
  94. package/dist/services/sensorService.d.ts +15 -0
  95. package/dist/services/sensorService.d.ts.map +1 -0
  96. package/dist/services/sensorService.js +69 -0
  97. package/dist/services/sensorService.js.map +1 -0
  98. package/dist/services/smartThingsCommand.d.ts +7 -0
  99. package/dist/services/smartThingsCommand.d.ts.map +1 -0
  100. package/dist/services/smartThingsCommand.js +12 -0
  101. package/dist/services/smartThingsCommand.js.map +1 -0
  102. package/dist/services/smokeDetector.d.ts +10 -0
  103. package/dist/services/smokeDetector.d.ts.map +1 -0
  104. package/dist/services/smokeDetector.js +27 -0
  105. package/dist/services/smokeDetector.js.map +1 -0
  106. package/dist/services/statelessProgrammableSwitchService.d.ts +12 -0
  107. package/dist/services/statelessProgrammableSwitchService.d.ts.map +1 -0
  108. package/dist/services/statelessProgrammableSwitchService.js +94 -0
  109. package/dist/services/statelessProgrammableSwitchService.js.map +1 -0
  110. package/dist/services/switchService.d.ts +12 -0
  111. package/dist/services/switchService.d.ts.map +1 -0
  112. package/dist/services/switchService.js +72 -0
  113. package/dist/services/switchService.js.map +1 -0
  114. package/dist/services/temperatureService.d.ts +11 -0
  115. package/dist/services/temperatureService.d.ts.map +1 -0
  116. package/dist/services/temperatureService.js +32 -0
  117. package/dist/services/temperatureService.js.map +1 -0
  118. package/dist/services/thermostatService.d.ts +22 -0
  119. package/dist/services/thermostatService.d.ts.map +1 -0
  120. package/dist/services/thermostatService.js +273 -0
  121. package/dist/services/thermostatService.js.map +1 -0
  122. package/dist/services/valveService.d.ts +12 -0
  123. package/dist/services/valveService.d.ts.map +1 -0
  124. package/dist/services/valveService.js +59 -0
  125. package/dist/services/valveService.js.map +1 -0
  126. package/dist/services/windowCoveringService.d.ts +36 -0
  127. package/dist/services/windowCoveringService.d.ts.map +1 -0
  128. package/dist/services/windowCoveringService.js +158 -0
  129. package/dist/services/windowCoveringService.js.map +1 -0
  130. package/dist/settings.d.ts +9 -0
  131. package/dist/settings.d.ts.map +1 -0
  132. package/dist/settings.js +12 -0
  133. package/dist/settings.js.map +1 -0
  134. package/dist/webhook/subscriptionHandler.d.ts +32 -0
  135. package/dist/webhook/subscriptionHandler.d.ts.map +1 -0
  136. package/dist/webhook/subscriptionHandler.js +68 -0
  137. package/dist/webhook/subscriptionHandler.js.map +1 -0
  138. package/dist/webhook/webhookServer.d.ts +19 -0
  139. package/dist/webhook/webhookServer.d.ts.map +1 -0
  140. package/dist/webhook/webhookServer.js +125 -0
  141. package/dist/webhook/webhookServer.js.map +1 -0
  142. package/package.json +57 -0
@@ -0,0 +1,168 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ exports.SmartThingsAuth = void 0;
30
+ const crypto = __importStar(require("crypto"));
31
+ const axios_1 = __importDefault(require("axios"));
32
+ const tokenManager_1 = require("./tokenManager");
33
+ const SMARTTHINGS_AUTH_URL = 'https://api.smartthings.com/oauth/authorize';
34
+ const SMARTTHINGS_TOKEN_URL = 'https://api.smartthings.com/oauth/token';
35
+ class SmartThingsAuth {
36
+ constructor(clientId, clientSecret, log, platform, storagePath, webhookServer) {
37
+ this.clientId = clientId;
38
+ this.clientSecret = clientSecret;
39
+ this.log = log;
40
+ this.platform = platform;
41
+ this.webhookServer = webhookServer;
42
+ this.state = null;
43
+ this.tokenManager = new tokenManager_1.TokenManager(log, storagePath, this.startAuthFlow.bind(this), this.refreshTokens.bind(this));
44
+ this.webhookServer.setAuthHandler(this);
45
+ }
46
+ async handleOAuthCallback(query, res) {
47
+ try {
48
+ if (!query.code || !query.state) {
49
+ throw new Error('Missing code or state parameter');
50
+ }
51
+ if (query.state !== this.state) {
52
+ throw new Error('Invalid state parameter');
53
+ }
54
+ const tokens = await this.exchangeCodeForTokens(query.code);
55
+ await this.tokenManager.updateTokens(tokens);
56
+ res.writeHead(200, { 'Content-Type': 'text/html' });
57
+ res.end('<h1>Authentication successful!</h1><p>You can close this window and restart Homebridge.</p>');
58
+ this.log.info('Successfully authenticated with SmartThings');
59
+ }
60
+ catch (error) {
61
+ this.log.error('OAuth callback error:', error);
62
+ res.writeHead(500, { 'Content-Type': 'text/html' });
63
+ res.end('<h1>Authentication failed</h1><p>Please try again.</p>');
64
+ }
65
+ }
66
+ async exchangeCodeForTokens(code) {
67
+ // Create Basic Auth header from client credentials
68
+ const basicAuth = Buffer.from(`${this.clientId}:${this.clientSecret}`).toString('base64');
69
+ // Build redirect URI with optional port
70
+ let redirectUri = this.platform.config.server_url;
71
+ if (!redirectUri.endsWith('/')) {
72
+ redirectUri += '/';
73
+ }
74
+ redirectUri += 'oauth/callback';
75
+ const params = new URLSearchParams();
76
+ params.append('grant_type', 'authorization_code');
77
+ params.append('code', code);
78
+ params.append('redirect_uri', redirectUri);
79
+ const response = await axios_1.default.post(SMARTTHINGS_TOKEN_URL, params, {
80
+ headers: {
81
+ 'Authorization': `Basic ${basicAuth}`,
82
+ 'Content-Type': 'application/x-www-form-urlencoded'
83
+ }
84
+ });
85
+ return response.data;
86
+ }
87
+ // Accepts refreshToken, performs API call, returns new token data
88
+ async refreshTokens(refreshToken) {
89
+ try {
90
+ if (!refreshToken) {
91
+ throw new Error('No refresh token provided to refreshTokens method');
92
+ }
93
+ this.log.debug('Attempting to refresh tokens via API call.');
94
+ // Create Basic Auth header from client credentials
95
+ const basicAuth = Buffer.from(`${this.clientId}:${this.clientSecret}`).toString('base64');
96
+ const params = new URLSearchParams();
97
+ params.append('grant_type', 'refresh_token');
98
+ params.append('refresh_token', refreshToken);
99
+ const response = await axios_1.default.post(SMARTTHINGS_TOKEN_URL, params, {
100
+ headers: {
101
+ 'Authorization': `Basic ${basicAuth}`,
102
+ 'Content-Type': 'application/x-www-form-urlencoded'
103
+ }
104
+ });
105
+ this.log.info('Successfully obtained new tokens from API.');
106
+ return response.data;
107
+ }
108
+ catch (error) {
109
+ this.log.error('Error during token refresh API call:', error);
110
+ throw error;
111
+ }
112
+ }
113
+ startAuthFlow() {
114
+ this.state = crypto.randomBytes(32).toString('hex');
115
+ const authUrl = new URL(SMARTTHINGS_AUTH_URL);
116
+ authUrl.searchParams.append('client_id', this.clientId);
117
+ authUrl.searchParams.append('response_type', 'code');
118
+ // Build redirect URI with optional port
119
+ let redirectUri = this.platform.config.server_url;
120
+ if (!redirectUri.endsWith('/')) {
121
+ redirectUri += '/';
122
+ }
123
+ redirectUri += 'oauth/callback';
124
+ authUrl.searchParams.append('redirect_uri', redirectUri);
125
+ authUrl.searchParams.append('scope', 'r:devices:* x:devices:* r:locations:*');
126
+ authUrl.searchParams.append('state', this.state);
127
+ this.log.warn('\n=================================================');
128
+ this.log.warn('SmartThings Authentication Required');
129
+ this.log.warn('Please visit this URL to authorize with SmartThings:');
130
+ this.log.warn(authUrl.toString());
131
+ this.log.warn('=================================================\n');
132
+ this.log.warn('Restart Homebridge after authentication');
133
+ }
134
+ async initialize() {
135
+ const accessToken = this.tokenManager.getAccessToken();
136
+ let authFlowStarted = false;
137
+ if (!accessToken || !this.tokenManager.isTokenValid()) {
138
+ if (this.tokenManager.isRefreshTokenValid()) {
139
+ try {
140
+ const currentRefreshToken = this.tokenManager.getRefreshToken();
141
+ if (currentRefreshToken) {
142
+ await this.refreshTokens(currentRefreshToken);
143
+ }
144
+ else {
145
+ this.log.warn('No refresh token found during initialization.');
146
+ this.startAuthFlow();
147
+ authFlowStarted = true;
148
+ }
149
+ }
150
+ catch (error) {
151
+ this.log.warn('Token refresh failed during initialization, starting auth flow.');
152
+ this.startAuthFlow();
153
+ authFlowStarted = true;
154
+ }
155
+ }
156
+ else {
157
+ this.startAuthFlow();
158
+ authFlowStarted = true;
159
+ }
160
+ }
161
+ return authFlowStarted; // Return true if auth flow was started
162
+ }
163
+ getAccessToken() {
164
+ return this.tokenManager.getAccessToken();
165
+ }
166
+ }
167
+ exports.SmartThingsAuth = SmartThingsAuth;
168
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/auth/auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import { Logger } from 'homebridge';
2
+ export interface TokenData {
3
+ access_token: string;
4
+ refresh_token: string;
5
+ expires_in: number;
6
+ expires_at: number;
7
+ refresh_token_expires_at: number;
8
+ installed_app_id?: string;
9
+ location_id?: string;
10
+ }
11
+ export declare class TokenManager {
12
+ private readonly log;
13
+ private tokenPath;
14
+ private tokenData;
15
+ private refreshTimer;
16
+ private readonly REFRESH_BEFORE_EXPIRY;
17
+ private readonly REFRESH_CHECK_INTERVAL;
18
+ private startAuthFlowCallback;
19
+ private refreshTokenApiCallback;
20
+ constructor(log: Logger, storagePath: string, startAuthFlowCallback: () => void, refreshTokenApiCallback: (refreshToken: string) => Promise<Partial<TokenData>>);
21
+ private startRefreshMonitor;
22
+ private checkAndRefreshTokens;
23
+ private loadTokens;
24
+ private saveTokens;
25
+ updateTokens(tokenData: Partial<TokenData>): Promise<void>;
26
+ getAccessToken(): string | null;
27
+ getRefreshToken(): string | null;
28
+ isTokenValid(): boolean;
29
+ isRefreshTokenValid(): boolean;
30
+ clearTokens(): void;
31
+ getTokenExpiryInfo(): {
32
+ accessTokenExpiresIn: number;
33
+ refreshTokenExpiresIn: number;
34
+ };
35
+ }
36
+ //# sourceMappingURL=tokenManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokenManager.d.ts","sourceRoot":"","sources":["../../src/auth/tokenManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAKpC,MAAM,WAAW,SAAS;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,wBAAwB,EAAE,MAAM,CAAC;IACjC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,qBAAa,YAAY;IAUrB,OAAO,CAAC,QAAQ,CAAC,GAAG;IATtB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,SAAS,CAA0B;IAC3C,OAAO,CAAC,YAAY,CAA+B;IACnD,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAiB;IACvD,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAa;IACpD,OAAO,CAAC,qBAAqB,CAAa;IAC1C,OAAO,CAAC,uBAAuB,CAAwD;gBAGpE,GAAG,EAAE,MAAM,EAC5B,WAAW,EAAE,MAAM,EACnB,qBAAqB,EAAE,MAAM,IAAI,EACjC,uBAAuB,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAShF,OAAO,CAAC,mBAAmB;YAYb,qBAAqB;IA6BnC,OAAO,CAAC,UAAU;IAYlB,OAAO,CAAC,UAAU;IAWL,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAyChE,cAAc,IAAI,MAAM,GAAG,IAAI;IAI/B,eAAe,IAAI,MAAM,GAAG,IAAI;IAIhC,YAAY,IAAI,OAAO;IAKvB,mBAAmB,IAAI,OAAO;IAK9B,WAAW,IAAI,IAAI;IAUnB,kBAAkB,IAAI;QAAE,oBAAoB,EAAE,MAAM,CAAC;QAAC,qBAAqB,EAAE,MAAM,CAAA;KAAE;CAW7F"}
@@ -0,0 +1,180 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.TokenManager = void 0;
27
+ const fs = __importStar(require("fs"));
28
+ const path = __importStar(require("path"));
29
+ class TokenManager {
30
+ constructor(log, storagePath, startAuthFlowCallback, refreshTokenApiCallback) {
31
+ this.log = log;
32
+ this.tokenData = null;
33
+ this.refreshTimer = null;
34
+ this.REFRESH_BEFORE_EXPIRY = 5 * 60 * 1000; // Refresh 5 minutes before expiry
35
+ this.REFRESH_CHECK_INTERVAL = 60 * 1000; // Check every minute
36
+ this.tokenPath = path.join(storagePath, 'smartthings_tokens.json');
37
+ this.startAuthFlowCallback = startAuthFlowCallback;
38
+ this.refreshTokenApiCallback = refreshTokenApiCallback;
39
+ this.loadTokens();
40
+ this.startRefreshMonitor();
41
+ }
42
+ startRefreshMonitor() {
43
+ // Clear any existing timer
44
+ if (this.refreshTimer) {
45
+ clearInterval(this.refreshTimer);
46
+ }
47
+ // Start a periodic check for token refresh
48
+ this.refreshTimer = setInterval(() => {
49
+ this.checkAndRefreshTokens();
50
+ }, this.REFRESH_CHECK_INTERVAL);
51
+ }
52
+ async checkAndRefreshTokens() {
53
+ // Only proceed if we actually have token data AND a refresh token
54
+ if (!this.tokenData || !this.tokenData.refresh_token) {
55
+ this.log.debug('checkAndRefreshTokens: Skipping refresh check as token data or refresh token is missing.');
56
+ return;
57
+ }
58
+ const now = Date.now();
59
+ const timeUntilExpiry = this.tokenData.expires_at - now;
60
+ // If access token is about to expire, refresh it
61
+ if (timeUntilExpiry <= this.REFRESH_BEFORE_EXPIRY) {
62
+ this.log.debug('Access token is about to expire, refreshing tokens');
63
+ try {
64
+ const currentRefreshToken = this.getRefreshToken();
65
+ // Call the API callback with the current refresh token
66
+ const newTokenData = await this.refreshTokenApiCallback(currentRefreshToken);
67
+ // Update internal tokens with the result from the API call
68
+ await this.updateTokens(newTokenData);
69
+ this.log.info('Successfully refreshed access token using API callback.');
70
+ }
71
+ catch (error) {
72
+ // If the API callback fails (e.g., invalid refresh token), trigger full auth flow
73
+ this.log.error('API token refresh failed:', error);
74
+ this.log.warn('Starting new auth flow due to refresh failure.');
75
+ this.startAuthFlowCallback();
76
+ }
77
+ }
78
+ }
79
+ loadTokens() {
80
+ try {
81
+ if (fs.existsSync(this.tokenPath)) {
82
+ const data = fs.readFileSync(this.tokenPath, 'utf8');
83
+ this.tokenData = JSON.parse(data);
84
+ this.log.debug('Loaded existing tokens from storage');
85
+ }
86
+ }
87
+ catch (error) {
88
+ this.log.error('Error loading tokens:', error);
89
+ }
90
+ }
91
+ saveTokens() {
92
+ try {
93
+ if (this.tokenData) {
94
+ fs.writeFileSync(this.tokenPath, JSON.stringify(this.tokenData, null, 2));
95
+ this.log.debug('Saved tokens to storage');
96
+ }
97
+ }
98
+ catch (error) {
99
+ this.log.error('Error saving tokens:', error);
100
+ }
101
+ }
102
+ async updateTokens(tokenData) {
103
+ var _a;
104
+ const oldAccessToken = (_a = this.tokenData) === null || _a === void 0 ? void 0 : _a.access_token;
105
+ this.tokenData = {
106
+ ...this.tokenData,
107
+ ...tokenData,
108
+ expires_at: Date.now() + (tokenData.expires_in || 0) * 1000,
109
+ refresh_token_expires_at: Date.now() + 30 * 24 * 60 * 60 * 1000, // 30 days
110
+ };
111
+ // Save tokens first
112
+ this.saveTokens();
113
+ // Update platform config only if access token actually changed
114
+ if (tokenData.access_token && tokenData.access_token !== oldAccessToken) {
115
+ // This part requires access to platform.config and platform.api,
116
+ // which we no longer directly have. This needs rethinking.
117
+ // For now, commenting out the config update.
118
+ // TODO: Find a way to update platform config without circular dependency.
119
+ /*
120
+ try {
121
+ // Save the updated config to disk
122
+ const configPath = this.platform.api.user.configPath();
123
+ const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
124
+
125
+ // Find and update our platform's config
126
+ const platformConfig = config.platforms.find(p =>
127
+ p.platform === 'HomeBridgeSmartThings' && p.name === this.platform.config.name
128
+ );
129
+
130
+ if (platformConfig) {
131
+ platformConfig.AccessToken = tokenData.access_token;
132
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 4));
133
+ this.log.debug('Updated AccessToken in Homebridge config');
134
+ }
135
+ } catch (error) {
136
+ this.log.error('Error updating platform config:', error);
137
+ }
138
+ */
139
+ }
140
+ }
141
+ getAccessToken() {
142
+ var _a;
143
+ return ((_a = this.tokenData) === null || _a === void 0 ? void 0 : _a.access_token) || null;
144
+ }
145
+ getRefreshToken() {
146
+ var _a;
147
+ return ((_a = this.tokenData) === null || _a === void 0 ? void 0 : _a.refresh_token) || null;
148
+ }
149
+ isTokenValid() {
150
+ if (!this.tokenData)
151
+ return false;
152
+ return Date.now() < (this.tokenData.expires_at - this.REFRESH_BEFORE_EXPIRY);
153
+ }
154
+ isRefreshTokenValid() {
155
+ if (!this.tokenData)
156
+ return false;
157
+ return Date.now() < (this.tokenData.refresh_token_expires_at - this.REFRESH_BEFORE_EXPIRY);
158
+ }
159
+ clearTokens() {
160
+ this.tokenData = null;
161
+ if (fs.existsSync(this.tokenPath)) {
162
+ fs.unlinkSync(this.tokenPath);
163
+ }
164
+ if (this.refreshTimer) {
165
+ clearInterval(this.refreshTimer);
166
+ }
167
+ }
168
+ getTokenExpiryInfo() {
169
+ if (!this.tokenData) {
170
+ return { accessTokenExpiresIn: 0, refreshTokenExpiresIn: 0 };
171
+ }
172
+ const now = Date.now();
173
+ return {
174
+ accessTokenExpiresIn: Math.max(0, this.tokenData.expires_at - now),
175
+ refreshTokenExpiresIn: Math.max(0, this.tokenData.refresh_token_expires_at - now),
176
+ };
177
+ }
178
+ }
179
+ exports.TokenManager = TokenManager;
180
+ //# sourceMappingURL=tokenManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokenManager.js","sourceRoot":"","sources":["../../src/auth/tokenManager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ /// <reference types="node" />
2
+ import { PlatformAccessory, Logger, API, Characteristic, CharacteristicValue, Service, WithUUID } from 'homebridge';
3
+ import axios = require('axios');
4
+ import { IKHomeBridgeHomebridgePlatform } from './platform';
5
+ import { ShortEvent } from './webhook/subscriptionHandler';
6
+ type DeviceStatus = {
7
+ timestamp: number;
8
+ status: any;
9
+ };
10
+ /**
11
+ * Platform Accessory
12
+ * An instance of this class is created for each accessory your platform registers
13
+ * Each accessory may expose multiple services of different service types.
14
+ */
15
+ export declare abstract class BasePlatformAccessory {
16
+ /**
17
+ * These are just used to create a working example
18
+ * You should implement your own code to track the state of your accessory
19
+ */
20
+ protected accessory: PlatformAccessory;
21
+ protected platform: IKHomeBridgeHomebridgePlatform;
22
+ readonly name: string;
23
+ protected characteristic: typeof Characteristic;
24
+ protected log: Logger;
25
+ protected baseURL: string;
26
+ protected key: string;
27
+ protected axInstance: axios.AxiosInstance;
28
+ protected commandURL: string;
29
+ protected statusURL: string;
30
+ protected healthURL: string;
31
+ protected api: API;
32
+ protected online: boolean;
33
+ protected deviceStatus: DeviceStatus;
34
+ protected failureCount: number;
35
+ protected giveUpTime: number;
36
+ protected commandInProgress: boolean;
37
+ protected lastCommandCompleted: number;
38
+ protected statusQueryInProgress: boolean;
39
+ protected lastStatusResult: boolean;
40
+ get id(): string;
41
+ constructor(platform: IKHomeBridgeHomebridgePlatform, accessory: PlatformAccessory);
42
+ abstract processEvent(event: ShortEvent): void;
43
+ protected refreshStatus(): Promise<boolean>;
44
+ protected startPollingState(pollSeconds: number, getValue: () => Promise<CharacteristicValue>, service: Service, chracteristic: WithUUID<new () => Characteristic>, targetStateCharacteristic?: WithUUID<new () => Characteristic>, getTargetState?: () => Promise<CharacteristicValue>): NodeJS.Timer | void;
45
+ sendCommand(capability: string, command: string, args?: unknown[]): Promise<boolean>;
46
+ private waitFor;
47
+ }
48
+ export {};
49
+ //# sourceMappingURL=basePlatformAccessory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"basePlatformAccessory.d.ts","sourceRoot":"","sources":["../src/basePlatformAccessory.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,EAAE,GAAG,EAAE,cAAc,EAAE,mBAAmB,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACpH,OAAO,KAAK,GAAG,QAAQ,OAAO,CAAC,CAAC;AAChC,OAAO,EAAE,8BAA8B,EAAE,MAAM,YAAY,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAE3D,KAAK,YAAY,GAAG;IAClB,SAAS,EAAE,MAAM,CAAC;IAElB,MAAM,EAAE,GAAG,CAAC;CACb,CAAC;AACF;;;;GAIG;AACH,8BAAsB,qBAAqB;IAGzC;;;OAGG;IAEH,SAAS,CAAC,SAAS,EAAE,iBAAiB,CAAC;IACvC,SAAS,CAAC,QAAQ,EAAE,8BAA8B,CAAC;IACnD,SAAgB,IAAI,EAAE,MAAM,CAAC;IAC7B,SAAS,CAAC,cAAc,EAAE,OAAO,cAAc,CAAC;IAChD,SAAS,CAAC,GAAG,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,GAAG,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,UAAU,EAAE,KAAK,CAAC,aAAa,CAAC;IAC1C,SAAS,CAAC,UAAU,EAAE,MAAM,CAAC;IAC7B,SAAS,CAAC,SAAS,EAAE,MAAM,CAAC;IAC5B,SAAS,CAAC,SAAS,EAAE,MAAM,CAAC;IAC5B,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC;IACnB,SAAS,CAAC,MAAM,UAAQ;IACxB,SAAS,CAAC,YAAY,EAAE,YAAY,CAAuC;IAC3E,SAAS,CAAC,YAAY,SAAK;IAC3B,SAAS,CAAC,UAAU,SAAK;IACzB,SAAS,CAAC,iBAAiB,UAAS;IACpC,SAAS,CAAC,oBAAoB,SAAK;IAEnC,SAAS,CAAC,qBAAqB,UAAS;IACxC,SAAS,CAAC,gBAAgB,UAAQ;IAElC,IAAI,EAAE,WAEL;gBAGC,QAAQ,EAAE,8BAA8B,EACxC,SAAS,EAAE,iBAAiB;aAyCd,YAAY,CAAC,KAAK,EAAE,UAAU,GAAE,IAAI;cAMpC,aAAa,IAAI,OAAO,CAAC,OAAO,CAAC;IA8CjD,SAAS,CAAC,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC,mBAAmB,CAAC,EAAE,OAAO,EAAE,OAAO,EAC7G,aAAa,EAAE,QAAQ,CAAC,UAAU,cAAc,CAAC,EAAE,yBAAyB,CAAC,EAAE,QAAQ,CAAC,UAAU,cAAc,CAAC,EACjH,cAAc,CAAC,EAAE,MAAM,OAAO,CAAC,mBAAmB,CAAC,GAAE,MAAM,CAAC,KAAK,GAAC,IAAI;IA6ClE,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;YA0C5E,OAAO;CAiBtB"}