node-switchbot 4.0.0-beta.1 → 4.0.0-beta.3

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 (170) hide show
  1. package/BLE.md +63 -0
  2. package/CHANGELOG.md +34 -0
  3. package/README.md +6 -0
  4. package/dist/devices/base.d.ts +59 -5
  5. package/dist/devices/base.d.ts.map +1 -1
  6. package/dist/devices/base.js +280 -28
  7. package/dist/devices/base.js.map +1 -1
  8. package/dist/devices/wo-hand.d.ts +35 -0
  9. package/dist/devices/wo-hand.d.ts.map +1 -1
  10. package/dist/devices/wo-hand.js +87 -0
  11. package/dist/devices/wo-hand.js.map +1 -1
  12. package/dist/settings.d.ts +6 -0
  13. package/dist/settings.d.ts.map +1 -1
  14. package/dist/settings.js +6 -0
  15. package/dist/settings.js.map +1 -1
  16. package/dist/switchbot.d.ts.map +1 -1
  17. package/dist/switchbot.js +14 -0
  18. package/dist/switchbot.js.map +1 -1
  19. package/dist/types/index.d.ts +12 -0
  20. package/dist/types/index.d.ts.map +1 -1
  21. package/dist/types/index.js.map +1 -1
  22. package/dist/utils/bot-ble.d.ts +36 -0
  23. package/dist/utils/bot-ble.d.ts.map +1 -0
  24. package/dist/utils/bot-ble.js +107 -0
  25. package/dist/utils/bot-ble.js.map +1 -0
  26. package/dist/utils/circuit-breaker.d.ts +98 -0
  27. package/dist/utils/circuit-breaker.d.ts.map +1 -0
  28. package/dist/utils/circuit-breaker.js +187 -0
  29. package/dist/utils/circuit-breaker.js.map +1 -0
  30. package/dist/utils/connection-tracker.d.ts +66 -0
  31. package/dist/utils/connection-tracker.d.ts.map +1 -0
  32. package/dist/utils/connection-tracker.js +184 -0
  33. package/dist/utils/connection-tracker.js.map +1 -0
  34. package/dist/utils/fallback-handler.d.ts +68 -0
  35. package/dist/utils/fallback-handler.d.ts.map +1 -0
  36. package/dist/utils/fallback-handler.js +131 -0
  37. package/dist/utils/fallback-handler.js.map +1 -0
  38. package/dist/utils/index.d.ts +5 -0
  39. package/dist/utils/index.d.ts.map +1 -1
  40. package/dist/utils/index.js +7 -0
  41. package/dist/utils/index.js.map +1 -1
  42. package/dist/utils/retry.d.ts +55 -0
  43. package/dist/utils/retry.d.ts.map +1 -0
  44. package/dist/utils/retry.js +95 -0
  45. package/dist/utils/retry.js.map +1 -0
  46. package/docs/assets/hierarchy.js +1 -1
  47. package/docs/assets/search.js +1 -1
  48. package/docs/classes/APIError.html +2 -2
  49. package/docs/classes/APINotAvailableError.html +2 -2
  50. package/docs/classes/BLEConnection.html +9 -9
  51. package/docs/classes/BLENotAvailableError.html +2 -2
  52. package/docs/classes/BLEScanner.html +8 -8
  53. package/docs/classes/CommandFailedError.html +2 -2
  54. package/docs/classes/ConnectionTimeoutError.html +2 -2
  55. package/docs/classes/DeviceManager.html +13 -13
  56. package/docs/classes/DeviceNotFoundError.html +2 -2
  57. package/docs/classes/DiscoveryError.html +2 -2
  58. package/docs/classes/OpenAPIClient.html +24 -24
  59. package/docs/classes/SwitchBot.html +11 -11
  60. package/docs/classes/SwitchBotDevice.html +33 -15
  61. package/docs/classes/SwitchBotError.html +2 -2
  62. package/docs/classes/ValidationError.html +2 -2
  63. package/docs/classes/WoAirPurifier.html +36 -18
  64. package/docs/classes/WoAirPurifierTable.html +36 -18
  65. package/docs/classes/WoBlindTilt.html +38 -20
  66. package/docs/classes/WoBulb.html +37 -19
  67. package/docs/classes/WoCeilingLight.html +37 -19
  68. package/docs/classes/WoContact.html +32 -14
  69. package/docs/classes/WoCurtain.html +36 -18
  70. package/docs/classes/WoHand.html +45 -19
  71. package/docs/classes/WoHub2.html +32 -14
  72. package/docs/classes/WoHub3.html +32 -14
  73. package/docs/classes/WoHumi.html +36 -18
  74. package/docs/classes/WoHumi2.html +36 -18
  75. package/docs/classes/WoIOSensorTH.html +32 -14
  76. package/docs/classes/WoKeypad.html +32 -14
  77. package/docs/classes/WoLeak.html +32 -14
  78. package/docs/classes/WoPlugMiniJP.html +35 -17
  79. package/docs/classes/WoPlugMiniUS.html +35 -17
  80. package/docs/classes/WoPresence.html +32 -14
  81. package/docs/classes/WoRelaySwitch1.html +35 -17
  82. package/docs/classes/WoRelaySwitch1PM.html +35 -17
  83. package/docs/classes/WoRemote.html +32 -14
  84. package/docs/classes/WoSensorTH.html +32 -14
  85. package/docs/classes/WoSensorTHPlus.html +32 -14
  86. package/docs/classes/WoSensorTHPro.html +32 -14
  87. package/docs/classes/WoSensorTHProCO2.html +32 -14
  88. package/docs/classes/WoSmartLock.html +34 -16
  89. package/docs/classes/WoSmartLockPro.html +35 -17
  90. package/docs/classes/WoStrip.html +37 -19
  91. package/docs/enums/LogLevel.html +2 -2
  92. package/docs/enums/SwitchBotBLEModel.html +2 -2
  93. package/docs/enums/SwitchBotBLEModelName.html +2 -2
  94. package/docs/functions/updateBaseURL.html +1 -1
  95. package/docs/hierarchy.html +1 -1
  96. package/docs/index.html +1 -1
  97. package/docs/interfaces/APICommandRequest.html +2 -2
  98. package/docs/interfaces/APICommandResponse.html +2 -2
  99. package/docs/interfaces/APIDevice.html +2 -2
  100. package/docs/interfaces/APIDeviceStatus.html +2 -2
  101. package/docs/interfaces/APIErrorResponse.html +2 -2
  102. package/docs/interfaces/APIResponse.html +2 -2
  103. package/docs/interfaces/AirPurifierCommands.html +2 -2
  104. package/docs/interfaces/AirPurifierServiceData.html +5 -5
  105. package/docs/interfaces/AirPurifierStatus.html +7 -7
  106. package/docs/interfaces/BLEAdvertisement.html +2 -2
  107. package/docs/interfaces/BLEScanOptions.html +5 -5
  108. package/docs/interfaces/BLEServiceData.html +5 -5
  109. package/docs/interfaces/BlindTiltCommands.html +2 -2
  110. package/docs/interfaces/BlindTiltServiceData.html +5 -5
  111. package/docs/interfaces/BlindTiltStatus.html +6 -6
  112. package/docs/interfaces/BotCommands.html +2 -2
  113. package/docs/interfaces/BotServiceData.html +5 -5
  114. package/docs/interfaces/BotStatus.html +6 -6
  115. package/docs/interfaces/BulbCommands.html +2 -2
  116. package/docs/interfaces/BulbServiceData.html +5 -5
  117. package/docs/interfaces/BulbStatus.html +6 -6
  118. package/docs/interfaces/CeilingLightCommands.html +2 -2
  119. package/docs/interfaces/CeilingLightServiceData.html +5 -5
  120. package/docs/interfaces/CeilingLightStatus.html +6 -6
  121. package/docs/interfaces/CommandResult.html +6 -6
  122. package/docs/interfaces/ContactServiceData.html +5 -5
  123. package/docs/interfaces/ContactStatus.html +6 -6
  124. package/docs/interfaces/CurtainCommands.html +2 -2
  125. package/docs/interfaces/CurtainServiceData.html +5 -5
  126. package/docs/interfaces/CurtainStatus.html +6 -6
  127. package/docs/interfaces/DeviceInfo.html +13 -13
  128. package/docs/interfaces/DeviceListResponse.html +2 -2
  129. package/docs/interfaces/DeviceStatus.html +6 -6
  130. package/docs/interfaces/DiscoveryOptions.html +7 -7
  131. package/docs/interfaces/HubServiceData.html +5 -5
  132. package/docs/interfaces/HubStatus.html +6 -6
  133. package/docs/interfaces/HumidifierCommands.html +2 -2
  134. package/docs/interfaces/HumidifierServiceData.html +6 -6
  135. package/docs/interfaces/HumidifierStatus.html +6 -6
  136. package/docs/interfaces/KeypadStatus.html +6 -6
  137. package/docs/interfaces/LeakServiceData.html +5 -5
  138. package/docs/interfaces/LeakStatus.html +6 -6
  139. package/docs/interfaces/LockCommands.html +2 -2
  140. package/docs/interfaces/LockServiceData.html +6 -6
  141. package/docs/interfaces/LockStatus.html +6 -6
  142. package/docs/interfaces/MeterServiceData.html +5 -5
  143. package/docs/interfaces/MeterStatus.html +6 -6
  144. package/docs/interfaces/MotionServiceData.html +5 -5
  145. package/docs/interfaces/MotionStatus.html +6 -6
  146. package/docs/interfaces/PlugCommands.html +2 -2
  147. package/docs/interfaces/PlugServiceData.html +5 -5
  148. package/docs/interfaces/PlugStatus.html +6 -6
  149. package/docs/interfaces/PresenceServiceData.html +5 -5
  150. package/docs/interfaces/PresenceStatus.html +6 -6
  151. package/docs/interfaces/RelaySwitchCommands.html +2 -2
  152. package/docs/interfaces/RelaySwitchServiceData.html +5 -5
  153. package/docs/interfaces/RelaySwitchStatus.html +6 -6
  154. package/docs/interfaces/RemoteStatus.html +6 -6
  155. package/docs/interfaces/SceneListResponse.html +2 -2
  156. package/docs/interfaces/StripCommands.html +2 -2
  157. package/docs/interfaces/StripServiceData.html +5 -5
  158. package/docs/interfaces/StripStatus.html +6 -6
  159. package/docs/interfaces/SwitchBotConfig.html +21 -9
  160. package/docs/interfaces/WebhookConfig.html +2 -2
  161. package/docs/interfaces/WebhookDetails.html +2 -2
  162. package/docs/interfaces/WebhookQueryResponse.html +2 -2
  163. package/docs/interfaces/WebhookSetupResponse.html +2 -2
  164. package/docs/media/BLE.md +63 -0
  165. package/docs/types/ConnectionType.html +1 -1
  166. package/docs/types/PhysicalDeviceType.html +1 -1
  167. package/docs/types/VirtualDeviceType.html +1 -1
  168. package/docs/variables/urls.html +1 -1
  169. package/package.json +2 -2
  170. package/tsconfig.build.json +17 -0
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Circuit breaker states
3
+ */
4
+ export declare enum CircuitBreakerState {
5
+ CLOSED = "CLOSED",// Normal operation
6
+ OPEN = "OPEN",// Failing, reject requests
7
+ HALF_OPEN = "HALF_OPEN"
8
+ }
9
+ /**
10
+ * Circuit breaker configuration
11
+ */
12
+ export interface CircuitBreakerConfig {
13
+ /** Failure threshold (0-1) to open circuit (default: 0.5) */
14
+ failureThreshold?: number;
15
+ /** Minimum number of requests before checking threshold (default: 5) */
16
+ minRequests?: number;
17
+ /** Time to wait before attempting recovery in milliseconds (default: 30000) */
18
+ resetTimeoutMs?: number;
19
+ /** Maximum number of requests in half-open state (default: 1) */
20
+ maxHalfOpenRequests?: number;
21
+ }
22
+ /**
23
+ * Circuit breaker statistics
24
+ */
25
+ export interface CircuitBreakerStats {
26
+ state: CircuitBreakerState;
27
+ successCount: number;
28
+ failureCount: number;
29
+ successRate: number;
30
+ totalRequests: number;
31
+ lastFailureTime?: Date;
32
+ lastRecoveryTime?: Date;
33
+ }
34
+ /**
35
+ * Circuit breaker for managing connection reliability
36
+ */
37
+ export declare class CircuitBreaker {
38
+ private name;
39
+ private state;
40
+ private successCount;
41
+ private failureCount;
42
+ private halfOpenAttempts;
43
+ private lastFailureTime?;
44
+ private lastRecoveryTime?;
45
+ private resetTimer?;
46
+ private logger;
47
+ private config;
48
+ constructor(name: string, config?: CircuitBreakerConfig, logLevel?: number);
49
+ /**
50
+ * Record a successful operation
51
+ */
52
+ recordSuccess(): void;
53
+ /**
54
+ * Record a failed operation
55
+ */
56
+ recordFailure(): void;
57
+ /**
58
+ * Check if circuit should open based on failure rate
59
+ */
60
+ private shouldOpen;
61
+ /**
62
+ * Transition to CLOSED state (recovered)
63
+ */
64
+ private transitionToClosed;
65
+ /**
66
+ * Transition to OPEN state (failing)
67
+ */
68
+ private transitionToOpen;
69
+ /**
70
+ * Check if the circuit allows operations
71
+ */
72
+ canExecute(): boolean;
73
+ /**
74
+ * Mark that we tried to execute in half-open state
75
+ */
76
+ markHalfOpenAttempt(): void;
77
+ /**
78
+ * Get current state
79
+ */
80
+ getState(): CircuitBreakerState;
81
+ /**
82
+ * Get current failure rate (0-1)
83
+ */
84
+ getFailureRate(): number;
85
+ /**
86
+ * Get statistics
87
+ */
88
+ getStats(): CircuitBreakerStats;
89
+ /**
90
+ * Reset circuit breaker (for testing)
91
+ */
92
+ reset(): void;
93
+ /**
94
+ * Cleanup
95
+ */
96
+ cleanup(): void;
97
+ }
98
+ //# sourceMappingURL=circuit-breaker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"circuit-breaker.d.ts","sourceRoot":"","sources":["../../src/utils/circuit-breaker.ts"],"names":[],"mappings":"AAOA;;GAEG;AACH,oBAAY,mBAAmB;IAC7B,MAAM,WAAW,CAAE,mBAAmB;IACtC,IAAI,SAAS,CAAE,2BAA2B;IAC1C,SAAS,cAAc;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,6DAA6D;IAC7D,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,wEAAwE;IACxE,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,+EAA+E;IAC/E,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,iEAAiE;IACjE,mBAAmB,CAAC,EAAE,MAAM,CAAA;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,mBAAmB,CAAA;IAC1B,YAAY,EAAE,MAAM,CAAA;IACpB,YAAY,EAAE,MAAM,CAAA;IACpB,WAAW,EAAE,MAAM,CAAA;IACnB,aAAa,EAAE,MAAM,CAAA;IACrB,eAAe,CAAC,EAAE,IAAI,CAAA;IACtB,gBAAgB,CAAC,EAAE,IAAI,CAAA;CACxB;AAED;;GAEG;AACH,qBAAa,cAAc;IAYvB,OAAO,CAAC,IAAI;IAXd,OAAO,CAAC,KAAK,CAAkD;IAC/D,OAAO,CAAC,YAAY,CAAI;IACxB,OAAO,CAAC,YAAY,CAAI;IACxB,OAAO,CAAC,gBAAgB,CAAI;IAC5B,OAAO,CAAC,eAAe,CAAC,CAAM;IAC9B,OAAO,CAAC,gBAAgB,CAAC,CAAM;IAC/B,OAAO,CAAC,UAAU,CAAC,CAAgB;IACnC,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,MAAM,CAAgC;gBAGpC,IAAI,EAAE,MAAM,EACpB,MAAM,GAAE,oBAAyB,EACjC,QAAQ,CAAC,EAAE,MAAM;IAYnB;;OAEG;IACH,aAAa,IAAI,IAAI;IAUrB;;OAEG;IACH,aAAa,IAAI,IAAI;IAmBrB;;OAEG;IACH,OAAO,CAAC,UAAU;IAWlB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAa1B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAkBxB;;OAEG;IACH,UAAU,IAAI,OAAO;IAarB;;OAEG;IACH,mBAAmB,IAAI,IAAI;IAM3B;;OAEG;IACH,QAAQ,IAAI,mBAAmB;IAI/B;;OAEG;IACH,cAAc,IAAI,MAAM;IAKxB;;OAEG;IACH,QAAQ,IAAI,mBAAmB;IAc/B;;OAEG;IACH,KAAK,IAAI,IAAI;IAeb;;OAEG;IACH,OAAO,IAAI,IAAI;CAMhB"}
@@ -0,0 +1,187 @@
1
+ /* Copyright(C) 2024-2026, donavanbecker (https://github.com/donavanbecker). All rights reserved.
2
+ *
3
+ * utils/circuit-breaker.ts: SwitchBot v4.0.0 - Circuit Breaker Pattern
4
+ */
5
+ import { Logger } from './index.js';
6
+ /**
7
+ * Circuit breaker states
8
+ */
9
+ export var CircuitBreakerState;
10
+ (function (CircuitBreakerState) {
11
+ CircuitBreakerState["CLOSED"] = "CLOSED";
12
+ CircuitBreakerState["OPEN"] = "OPEN";
13
+ CircuitBreakerState["HALF_OPEN"] = "HALF_OPEN";
14
+ })(CircuitBreakerState || (CircuitBreakerState = {}));
15
+ /**
16
+ * Circuit breaker for managing connection reliability
17
+ */
18
+ export class CircuitBreaker {
19
+ name;
20
+ state = CircuitBreakerState.CLOSED;
21
+ successCount = 0;
22
+ failureCount = 0;
23
+ halfOpenAttempts = 0;
24
+ lastFailureTime;
25
+ lastRecoveryTime;
26
+ resetTimer;
27
+ logger;
28
+ config;
29
+ constructor(name, config = {}, logLevel) {
30
+ this.name = name;
31
+ this.config = {
32
+ failureThreshold: config.failureThreshold ?? 0.5,
33
+ minRequests: config.minRequests ?? 5,
34
+ resetTimeoutMs: config.resetTimeoutMs ?? 30000,
35
+ maxHalfOpenRequests: config.maxHalfOpenRequests ?? 1,
36
+ };
37
+ this.logger = new Logger(`CircuitBreaker:${name}`, logLevel);
38
+ }
39
+ /**
40
+ * Record a successful operation
41
+ */
42
+ recordSuccess() {
43
+ this.successCount++;
44
+ if (this.state === CircuitBreakerState.HALF_OPEN) {
45
+ // Successful in Half-Open -> recover
46
+ this.logger.info(`${this.name}: circuit recovered (HALF_OPEN -> CLOSED)`);
47
+ this.transitionToClosed();
48
+ }
49
+ }
50
+ /**
51
+ * Record a failed operation
52
+ */
53
+ recordFailure() {
54
+ this.failureCount++;
55
+ this.lastFailureTime = new Date();
56
+ if (this.state === CircuitBreakerState.CLOSED) {
57
+ // Check if we should open the circuit
58
+ if (this.shouldOpen()) {
59
+ this.logger.warn(`${this.name}: circuit opened - failure rate ${this.getFailureRate().toFixed(2)}`);
60
+ this.transitionToOpen();
61
+ }
62
+ }
63
+ else if (this.state === CircuitBreakerState.HALF_OPEN) {
64
+ // Failed during recovery -> reopen
65
+ this.logger.warn(`${this.name}: circuit reopened (HALF_OPEN -> OPEN)`);
66
+ this.transitionToOpen();
67
+ }
68
+ }
69
+ /**
70
+ * Check if circuit should open based on failure rate
71
+ */
72
+ shouldOpen() {
73
+ const totalRequests = this.successCount + this.failureCount;
74
+ if (totalRequests < this.config.minRequests) {
75
+ return false;
76
+ }
77
+ const failureRate = this.failureCount / totalRequests;
78
+ return failureRate >= this.config.failureThreshold;
79
+ }
80
+ /**
81
+ * Transition to CLOSED state (recovered)
82
+ */
83
+ transitionToClosed() {
84
+ this.state = CircuitBreakerState.CLOSED;
85
+ this.successCount = 0;
86
+ this.failureCount = 0;
87
+ this.halfOpenAttempts = 0;
88
+ this.lastRecoveryTime = new Date();
89
+ if (this.resetTimer) {
90
+ clearTimeout(this.resetTimer);
91
+ this.resetTimer = undefined;
92
+ }
93
+ }
94
+ /**
95
+ * Transition to OPEN state (failing)
96
+ */
97
+ transitionToOpen() {
98
+ this.state = CircuitBreakerState.OPEN;
99
+ this.successCount = 0;
100
+ this.failureCount = 0;
101
+ this.halfOpenAttempts = 0;
102
+ // Schedule recovery attempt
103
+ if (this.resetTimer) {
104
+ clearTimeout(this.resetTimer);
105
+ }
106
+ this.resetTimer = setTimeout(() => {
107
+ this.logger.info(`${this.name}: attempting recovery (OPEN -> HALF_OPEN)`);
108
+ this.state = CircuitBreakerState.HALF_OPEN;
109
+ this.halfOpenAttempts = 0;
110
+ }, this.config.resetTimeoutMs);
111
+ }
112
+ /**
113
+ * Check if the circuit allows operations
114
+ */
115
+ canExecute() {
116
+ if (this.state === CircuitBreakerState.CLOSED) {
117
+ return true;
118
+ }
119
+ if (this.state === CircuitBreakerState.HALF_OPEN) {
120
+ return this.halfOpenAttempts < this.config.maxHalfOpenRequests;
121
+ }
122
+ // OPEN state
123
+ return false;
124
+ }
125
+ /**
126
+ * Mark that we tried to execute in half-open state
127
+ */
128
+ markHalfOpenAttempt() {
129
+ if (this.state === CircuitBreakerState.HALF_OPEN) {
130
+ this.halfOpenAttempts++;
131
+ }
132
+ }
133
+ /**
134
+ * Get current state
135
+ */
136
+ getState() {
137
+ return this.state;
138
+ }
139
+ /**
140
+ * Get current failure rate (0-1)
141
+ */
142
+ getFailureRate() {
143
+ const total = this.successCount + this.failureCount;
144
+ return total === 0 ? 0 : this.failureCount / total;
145
+ }
146
+ /**
147
+ * Get statistics
148
+ */
149
+ getStats() {
150
+ const totalRequests = this.successCount + this.failureCount;
151
+ return {
152
+ state: this.state,
153
+ successCount: this.successCount,
154
+ failureCount: this.failureCount,
155
+ successRate: totalRequests === 0 ? 1 : this.successCount / totalRequests,
156
+ totalRequests,
157
+ lastFailureTime: this.lastFailureTime,
158
+ lastRecoveryTime: this.lastRecoveryTime,
159
+ };
160
+ }
161
+ /**
162
+ * Reset circuit breaker (for testing)
163
+ */
164
+ reset() {
165
+ this.logger.debug(`${this.name}: reset`);
166
+ this.state = CircuitBreakerState.CLOSED;
167
+ this.successCount = 0;
168
+ this.failureCount = 0;
169
+ this.halfOpenAttempts = 0;
170
+ this.lastFailureTime = undefined;
171
+ this.lastRecoveryTime = undefined;
172
+ if (this.resetTimer) {
173
+ clearTimeout(this.resetTimer);
174
+ this.resetTimer = undefined;
175
+ }
176
+ }
177
+ /**
178
+ * Cleanup
179
+ */
180
+ cleanup() {
181
+ if (this.resetTimer) {
182
+ clearTimeout(this.resetTimer);
183
+ this.resetTimer = undefined;
184
+ }
185
+ }
186
+ }
187
+ //# sourceMappingURL=circuit-breaker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"circuit-breaker.js","sourceRoot":"","sources":["../../src/utils/circuit-breaker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,66 @@
1
+ import type { ConnectionType } from '../types/index.js';
2
+ /**
3
+ * Statistics for a single connection type
4
+ */
5
+ export interface ConnectionStats {
6
+ connectionType: ConnectionType;
7
+ successCount: number;
8
+ failureCount: number;
9
+ totalAttempts: number;
10
+ successRate: number;
11
+ averageLatencyMs: number;
12
+ lastAttemptTime?: Date;
13
+ lastSuccessTime?: Date;
14
+ lastFailureTime?: Date;
15
+ }
16
+ /**
17
+ * Tracks connection success/failure statistics per device per connection type
18
+ */
19
+ export declare class ConnectionTracker {
20
+ private deviceId;
21
+ private stats;
22
+ private logger;
23
+ constructor(deviceId: string, logLevel?: number);
24
+ /**
25
+ * Record a successful attempt
26
+ */
27
+ recordSuccess(connectionType: ConnectionType, latencyMs?: number): void;
28
+ /**
29
+ * Record a failed attempt
30
+ */
31
+ recordFailure(connectionType: ConnectionType): void;
32
+ /**
33
+ * Get statistics for a connection type
34
+ */
35
+ getStats(connectionType: ConnectionType): ConnectionStats | undefined;
36
+ /**
37
+ * Get all statistics
38
+ */
39
+ getAllStats(): ConnectionStats[];
40
+ /**
41
+ * Get the best connection type (highest success rate)
42
+ */
43
+ getBestConnection(availableTypes?: ConnectionType[]): ConnectionType | undefined;
44
+ /**
45
+ * Get the most recent successful connection type
46
+ */
47
+ getMostRecentSuccessful(availableTypes?: ConnectionType[]): ConnectionType | undefined;
48
+ /**
49
+ * Check if a connection type is considered reliable
50
+ * (e.g., success rate > 75% with at least 5 attempts)
51
+ */
52
+ isReliable(connectionType: ConnectionType, minAttempts?: number, minRate?: number): boolean;
53
+ /**
54
+ * Get connection recommendation with reasoning
55
+ */
56
+ getRecommendation(availableTypes?: ConnectionType[]): {
57
+ recommended: ConnectionType | undefined;
58
+ reason: string;
59
+ stats: ConnectionStats[];
60
+ };
61
+ /**
62
+ * Reset all statistics
63
+ */
64
+ reset(): void;
65
+ }
66
+ //# sourceMappingURL=connection-tracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection-tracker.d.ts","sourceRoot":"","sources":["../../src/utils/connection-tracker.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAIvD;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,cAAc,EAAE,cAAc,CAAA;IAC9B,YAAY,EAAE,MAAM,CAAA;IACpB,YAAY,EAAE,MAAM,CAAA;IACpB,aAAa,EAAE,MAAM,CAAA;IACrB,WAAW,EAAE,MAAM,CAAA;IACnB,gBAAgB,EAAE,MAAM,CAAA;IACxB,eAAe,CAAC,EAAE,IAAI,CAAA;IACtB,eAAe,CAAC,EAAE,IAAI,CAAA;IACtB,eAAe,CAAC,EAAE,IAAI,CAAA;CACvB;AAED;;GAEG;AACH,qBAAa,iBAAiB;IAK1B,OAAO,CAAC,QAAQ;IAJlB,OAAO,CAAC,KAAK,CAAkD;IAC/D,OAAO,CAAC,MAAM,CAAQ;gBAGZ,QAAQ,EAAE,MAAM,EACxB,QAAQ,CAAC,EAAE,MAAM;IAqBnB;;OAEG;IACH,aAAa,CAAC,cAAc,EAAE,cAAc,EAAE,SAAS,GAAE,MAAU,GAAG,IAAI;IAwB1E;;OAEG;IACH,aAAa,CAAC,cAAc,EAAE,cAAc,GAAG,IAAI;IAmBnD;;OAEG;IACH,QAAQ,CAAC,cAAc,EAAE,cAAc,GAAG,eAAe,GAAG,SAAS;IAIrE;;OAEG;IACH,WAAW,IAAI,eAAe,EAAE;IAIhC;;OAEG;IACH,iBAAiB,CAAC,cAAc,GAAE,cAAc,EAAmB,GAAG,cAAc,GAAG,SAAS;IAsBhG;;OAEG;IACH,uBAAuB,CAAC,cAAc,GAAE,cAAc,EAAmB,GAAG,cAAc,GAAG,SAAS;IAiBtG;;;OAGG;IACH,UAAU,CAAC,cAAc,EAAE,cAAc,EAAE,WAAW,GAAE,MAAU,EAAE,OAAO,GAAE,MAAa,GAAG,OAAO;IASpG;;OAEG;IACH,iBAAiB,CAAC,cAAc,GAAE,cAAc,EAAmB,GAAG;QACpE,WAAW,EAAE,cAAc,GAAG,SAAS,CAAA;QACvC,MAAM,EAAE,MAAM,CAAA;QACd,KAAK,EAAE,eAAe,EAAE,CAAA;KACzB;IAsCD;;OAEG;IACH,KAAK,IAAI,IAAI;CAad"}
@@ -0,0 +1,184 @@
1
+ /* Copyright(C) 2024-2026, donavanbecker (https://github.com/donavanbecker). All rights reserved.
2
+ *
3
+ * utils/connection-tracker.ts: SwitchBot v4.0.0 - Connection Success Tracking
4
+ */
5
+ import { Logger } from './index.js';
6
+ /**
7
+ * Tracks connection success/failure statistics per device per connection type
8
+ */
9
+ export class ConnectionTracker {
10
+ deviceId;
11
+ stats = new Map();
12
+ logger;
13
+ constructor(deviceId, logLevel) {
14
+ this.deviceId = deviceId;
15
+ this.logger = new Logger(`ConnectionTracker:${deviceId}`, logLevel);
16
+ // Initialize stats for all connection types
17
+ const connectionTypes = ['ble', 'api'];
18
+ for (const type of connectionTypes) {
19
+ this.stats.set(type, {
20
+ connectionType: type,
21
+ successCount: 0,
22
+ failureCount: 0,
23
+ totalAttempts: 0,
24
+ successRate: 1, // Start optimistic
25
+ averageLatencyMs: 0,
26
+ lastAttemptTime: undefined,
27
+ lastSuccessTime: undefined,
28
+ lastFailureTime: undefined,
29
+ });
30
+ }
31
+ }
32
+ /**
33
+ * Record a successful attempt
34
+ */
35
+ recordSuccess(connectionType, latencyMs = 0) {
36
+ const stat = this.stats.get(connectionType);
37
+ if (!stat) {
38
+ return;
39
+ }
40
+ stat.successCount++;
41
+ stat.totalAttempts++;
42
+ stat.lastAttemptTime = new Date();
43
+ stat.lastSuccessTime = new Date();
44
+ // Update average latency (exponential moving average)
45
+ const alpha = 0.3;
46
+ stat.averageLatencyMs = stat.averageLatencyMs * (1 - alpha) + latencyMs * alpha;
47
+ // Update success rate
48
+ stat.successRate = stat.totalAttempts === 0 ? 1 : stat.successCount / stat.totalAttempts;
49
+ this.logger.debug(`${connectionType}: success recorded`, {
50
+ successRate: stat.successRate.toFixed(2),
51
+ latency: latencyMs,
52
+ });
53
+ }
54
+ /**
55
+ * Record a failed attempt
56
+ */
57
+ recordFailure(connectionType) {
58
+ const stat = this.stats.get(connectionType);
59
+ if (!stat) {
60
+ return;
61
+ }
62
+ stat.failureCount++;
63
+ stat.totalAttempts++;
64
+ stat.lastAttemptTime = new Date();
65
+ stat.lastFailureTime = new Date();
66
+ // Update success rate
67
+ stat.successRate = stat.totalAttempts === 0 ? 1 : stat.successCount / stat.totalAttempts;
68
+ this.logger.debug(`${connectionType}: failure recorded`, {
69
+ successRate: stat.successRate.toFixed(2),
70
+ });
71
+ }
72
+ /**
73
+ * Get statistics for a connection type
74
+ */
75
+ getStats(connectionType) {
76
+ return this.stats.get(connectionType);
77
+ }
78
+ /**
79
+ * Get all statistics
80
+ */
81
+ getAllStats() {
82
+ return Array.from(this.stats.values());
83
+ }
84
+ /**
85
+ * Get the best connection type (highest success rate)
86
+ */
87
+ getBestConnection(availableTypes = ['ble', 'api']) {
88
+ let bestType;
89
+ let bestRate = -1;
90
+ for (const type of availableTypes) {
91
+ const stat = this.stats.get(type);
92
+ if (stat && stat.successRate > bestRate) {
93
+ bestRate = stat.successRate;
94
+ bestType = type;
95
+ }
96
+ }
97
+ if (bestType) {
98
+ const stat = this.stats.get(bestType);
99
+ if (stat.totalAttempts > 0) {
100
+ this.logger.debug(`Best connection: ${bestType} (success rate: ${stat.successRate.toFixed(2)})`);
101
+ }
102
+ }
103
+ return bestType;
104
+ }
105
+ /**
106
+ * Get the most recent successful connection type
107
+ */
108
+ getMostRecentSuccessful(availableTypes = ['ble', 'api']) {
109
+ let mostRecentType;
110
+ let mostRecentTime;
111
+ for (const type of availableTypes) {
112
+ const stat = this.stats.get(type);
113
+ if (stat?.lastSuccessTime) {
114
+ if (!mostRecentTime || stat.lastSuccessTime > mostRecentTime) {
115
+ mostRecentTime = stat.lastSuccessTime;
116
+ mostRecentType = type;
117
+ }
118
+ }
119
+ }
120
+ return mostRecentType;
121
+ }
122
+ /**
123
+ * Check if a connection type is considered reliable
124
+ * (e.g., success rate > 75% with at least 5 attempts)
125
+ */
126
+ isReliable(connectionType, minAttempts = 5, minRate = 0.75) {
127
+ const stat = this.stats.get(connectionType);
128
+ if (!stat) {
129
+ return false;
130
+ }
131
+ return stat.totalAttempts >= minAttempts && stat.successRate >= minRate;
132
+ }
133
+ /**
134
+ * Get connection recommendation with reasoning
135
+ */
136
+ getRecommendation(availableTypes = ['ble', 'api']) {
137
+ const stats = availableTypes.map(type => this.stats.get(type)).filter(Boolean);
138
+ // If no attempt history, recommend first available
139
+ if (stats.every(s => s.totalAttempts === 0)) {
140
+ return {
141
+ recommended: availableTypes[0],
142
+ reason: 'No history, using first available connection',
143
+ stats,
144
+ };
145
+ }
146
+ // Find most reliable based on success rate
147
+ const bestType = this.getBestConnection(availableTypes);
148
+ if (!bestType) {
149
+ return {
150
+ recommended: undefined,
151
+ reason: 'No available connections',
152
+ stats,
153
+ };
154
+ }
155
+ const bestStat = this.stats.get(bestType);
156
+ let reason = `${bestType} has best success rate (${bestStat.successRate.toFixed(2)})`;
157
+ // Add context about latency if applicable
158
+ if (bestStat.averageLatencyMs > 0) {
159
+ reason += ` with avg latency ${bestStat.averageLatencyMs.toFixed(0)}ms`;
160
+ }
161
+ return {
162
+ recommended: bestType,
163
+ reason,
164
+ stats,
165
+ };
166
+ }
167
+ /**
168
+ * Reset all statistics
169
+ */
170
+ reset() {
171
+ this.logger.debug('Resetting all statistics');
172
+ for (const stat of this.stats.values()) {
173
+ stat.successCount = 0;
174
+ stat.failureCount = 0;
175
+ stat.totalAttempts = 0;
176
+ stat.successRate = 1;
177
+ stat.averageLatencyMs = 0;
178
+ stat.lastAttemptTime = undefined;
179
+ stat.lastSuccessTime = undefined;
180
+ stat.lastFailureTime = undefined;
181
+ }
182
+ }
183
+ }
184
+ //# sourceMappingURL=connection-tracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection-tracker.js","sourceRoot":"","sources":["../../src/utils/connection-tracker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,68 @@
1
+ import type { ConnectionType } from '../types/index.js';
2
+ /**
3
+ * Information about a fallback event
4
+ */
5
+ export interface FallbackEvent {
6
+ deviceId: string;
7
+ primaryConnection: ConnectionType;
8
+ fallbackConnection: ConnectionType | undefined;
9
+ reason: string;
10
+ timestamp: Date;
11
+ attemptsCount?: number;
12
+ totalTimeMs?: number;
13
+ }
14
+ /**
15
+ * Type for custom fallback handler callbacks
16
+ */
17
+ export type FallbackHandler = (event: FallbackEvent) => void | Promise<void>;
18
+ /**
19
+ * Options for registering a fallback handler
20
+ */
21
+ export interface FallbackHandlerOptions {
22
+ /** Handler identifier for later removal */
23
+ id?: string;
24
+ /** Handler priority (higher = executes first) */
25
+ priority?: number;
26
+ }
27
+ /**
28
+ * Manages custom fallback handlers and events
29
+ */
30
+ export declare class FallbackHandlerManager {
31
+ private handlers;
32
+ private logger;
33
+ private handlerCounter;
34
+ constructor(logLevel?: number);
35
+ /**
36
+ * Register a custom fallback handler
37
+ */
38
+ register(handler: FallbackHandler, options?: FallbackHandlerOptions): string;
39
+ /**
40
+ * Unregister a fallback handler
41
+ */
42
+ unregister(id: string): boolean;
43
+ /**
44
+ * Emit a fallback event to all registered handlers
45
+ */
46
+ emit(event: FallbackEvent): Promise<void>;
47
+ /**
48
+ * Clear all handlers
49
+ */
50
+ clear(): void;
51
+ /**
52
+ * Get handler count
53
+ */
54
+ getHandlerCount(): number;
55
+ }
56
+ /**
57
+ * Built-in fallback handler: Log fallback events
58
+ */
59
+ export declare function createLoggingFallbackHandler(logLevel?: number): FallbackHandler;
60
+ /**
61
+ * Built-in fallback handler: Metrics/statistics collection
62
+ */
63
+ export declare function createMetricsCollectionHandler(): FallbackHandler;
64
+ /**
65
+ * Built-in fallback handler: Alert on repeated fallbacks
66
+ */
67
+ export declare function createAlertHandler(alertThreshold?: number): FallbackHandler;
68
+ //# sourceMappingURL=fallback-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fallback-handler.d.ts","sourceRoot":"","sources":["../../src/utils/fallback-handler.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAIvD;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAA;IAChB,iBAAiB,EAAE,cAAc,CAAA;IACjC,kBAAkB,EAAE,cAAc,GAAG,SAAS,CAAA;IAC9C,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,IAAI,CAAA;IACf,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;AAE5E;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,2CAA2C;IAC3C,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,iDAAiD;IACjD,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED;;GAEG;AACH,qBAAa,sBAAsB;IACjC,OAAO,CAAC,QAAQ,CAGH;IAEb,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,cAAc,CAAI;gBAEd,QAAQ,CAAC,EAAE,MAAM;IAI7B;;OAEG;IACH,QAAQ,CACN,OAAO,EAAE,eAAe,EACxB,OAAO,GAAE,sBAA2B,GACnC,MAAM;IAUT;;OAEG;IACH,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAQ/B;;OAEG;IACG,IAAI,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAqB/C;;OAEG;IACH,KAAK,IAAI,IAAI;IAKb;;OAEG;IACH,eAAe,IAAI,MAAM;CAG1B;AAED;;GAEG;AACH,wBAAgB,4BAA4B,CAAC,QAAQ,GAAE,MAAU,GAAG,eAAe,CAmBlF;AAED;;GAEG;AACH,wBAAgB,8BAA8B,IAAI,eAAe,CA+BhE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,cAAc,GAAE,MAAU,GAAG,eAAe,CAkB9E"}