@espressif/rainmaker-neo-base-sdk 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +40 -4
- package/dist/cjs/ESPDevice.js +6 -0
- package/dist/cjs/ESPDevice.js.map +1 -1
- package/dist/cjs/ESPRMNeoNode.js +33 -14
- package/dist/cjs/ESPRMNeoNode.js.map +1 -1
- package/dist/cjs/index.js +3 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/methods/ESPDevice/Provision.js +7 -0
- package/dist/cjs/methods/ESPDevice/Provision.js.map +1 -1
- package/dist/cjs/methods/ESPDevice/ResetWifiStatus.js +26 -0
- package/dist/cjs/methods/ESPDevice/ResetWifiStatus.js.map +1 -0
- package/dist/cjs/methods/ESPDevice/RetryNetworkCredentials.js +46 -0
- package/dist/cjs/methods/ESPDevice/RetryNetworkCredentials.js.map +1 -0
- package/dist/cjs/methods/ESPRMNeoNode/Sync.js +4 -1
- package/dist/cjs/methods/ESPRMNeoNode/Sync.js.map +1 -1
- package/dist/cjs/methods/ESPRMNeoUser/MQTT/AssumeRole.js +8 -9
- package/dist/cjs/methods/ESPRMNeoUser/MQTT/AssumeRole.js.map +1 -1
- package/dist/cjs/proto/esp_rmaker_chal_resp.js +5 -0
- package/dist/cjs/proto/esp_rmaker_chal_resp.js.map +1 -1
- package/dist/cjs/services/ESPRMNeoMqtt/ESPRMNeoMqtt.js +13 -0
- package/dist/cjs/services/ESPRMNeoMqtt/ESPRMNeoMqtt.js.map +1 -1
- package/dist/cjs/services/NodeMQTTOrchestrator.js +2 -5
- package/dist/cjs/services/NodeMQTTOrchestrator.js.map +1 -1
- package/dist/cjs/utils/constants.js +10 -0
- package/dist/cjs/utils/constants.js.map +1 -1
- package/dist/cjs/utils/nodeUtils.js +12 -1
- package/dist/cjs/utils/nodeUtils.js.map +1 -1
- package/dist/cjs/utils/waitForNodeOnline.js +7 -6
- package/dist/cjs/utils/waitForNodeOnline.js.map +1 -1
- package/dist/esm/ESPDevice.js +6 -0
- package/dist/esm/ESPDevice.js.map +1 -1
- package/dist/esm/ESPRMNeoNode.js +33 -14
- package/dist/esm/ESPRMNeoNode.js.map +1 -1
- package/dist/esm/index.js +3 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/methods/ESPDevice/Provision.js +7 -0
- package/dist/esm/methods/ESPDevice/Provision.js.map +1 -1
- package/dist/esm/methods/ESPDevice/ResetWifiStatus.js +24 -0
- package/dist/esm/methods/ESPDevice/ResetWifiStatus.js.map +1 -0
- package/dist/esm/methods/ESPDevice/RetryNetworkCredentials.js +44 -0
- package/dist/esm/methods/ESPDevice/RetryNetworkCredentials.js.map +1 -0
- package/dist/esm/methods/ESPRMNeoNode/Sync.js +4 -1
- package/dist/esm/methods/ESPRMNeoNode/Sync.js.map +1 -1
- package/dist/esm/methods/ESPRMNeoUser/MQTT/AssumeRole.js +9 -10
- package/dist/esm/methods/ESPRMNeoUser/MQTT/AssumeRole.js.map +1 -1
- package/dist/esm/proto/esp_rmaker_chal_resp.js +5 -0
- package/dist/esm/proto/esp_rmaker_chal_resp.js.map +1 -1
- package/dist/esm/services/ESPRMNeoMqtt/ESPRMNeoMqtt.js +13 -0
- package/dist/esm/services/ESPRMNeoMqtt/ESPRMNeoMqtt.js.map +1 -1
- package/dist/esm/services/NodeMQTTOrchestrator.js +2 -5
- package/dist/esm/services/NodeMQTTOrchestrator.js.map +1 -1
- package/dist/esm/utils/constants.js +10 -1
- package/dist/esm/utils/constants.js.map +1 -1
- package/dist/esm/utils/nodeUtils.js +12 -1
- package/dist/esm/utils/nodeUtils.js.map +1 -1
- package/dist/esm/utils/waitForNodeOnline.js +7 -6
- package/dist/esm/utils/waitForNodeOnline.js.map +1 -1
- package/dist/types/ESPDevice.d.ts +10 -0
- package/dist/types/ESPRMNeoNode.d.ts +17 -5
- package/dist/types/methods/ESPDevice/ResetWifiStatus.d.ts +18 -0
- package/dist/types/methods/ESPDevice/RetryNetworkCredentials.d.ts +22 -0
- package/dist/types/methods/ESPDevice/index.d.ts +2 -0
- package/dist/types/methods/ESPRMNeoUser/MQTT/AssumeRole.d.ts +25 -15
- package/dist/types/services/ESPRMNeoMqtt/ESPRMNeoMqtt.d.ts +10 -0
- package/dist/types/services/NodeMQTTOrchestrator.d.ts +2 -2
- package/dist/types/services/interfaces/MQTTTransport.d.ts +10 -0
- package/dist/types/types/provision.d.ts +10 -0
- package/dist/types/utils/constants.d.ts +10 -1
- package/dist/types/utils/waitForNodeOnline.d.ts +9 -3
- package/package.json +1 -1
package/dist/esm/ESPRMNeoNode.js
CHANGED
|
@@ -38,14 +38,19 @@ class ESPRMNeoNode {
|
|
|
38
38
|
subgroupIds = [];
|
|
39
39
|
devices = [];
|
|
40
40
|
services = [];
|
|
41
|
+
/**
|
|
42
|
+
* Last-known connectivity. Seeded from cached `connectivity_status` when
|
|
43
|
+
* present (cloud config does not provide it); otherwise starts offline until
|
|
44
|
+
* an MQTT shadow `online` update arrives.
|
|
45
|
+
*/
|
|
41
46
|
connectivityStatus = {
|
|
42
47
|
isConnected: false,
|
|
43
48
|
lastConnectionTimestamp: 0,
|
|
44
49
|
};
|
|
45
50
|
/**
|
|
46
51
|
* Transports currently usable for this node, keyed by mode.
|
|
47
|
-
* - `mqtt` (cloud) is added when the node
|
|
48
|
-
*
|
|
52
|
+
* - `mqtt` (cloud) is added when the node is connected and removed when it
|
|
53
|
+
* goes offline (from cached `connectivity_status` or shadow updates).
|
|
49
54
|
* - `local` is added/removed at runtime by a `localDiscovery` subscriber as the
|
|
50
55
|
* node appears/disappears on the LAN (via {@link addTransport}/{@link removeTransport}).
|
|
51
56
|
* Apps may also add custom string-keyed entries (pair with
|
|
@@ -78,16 +83,11 @@ class ESPRMNeoNode {
|
|
|
78
83
|
this.subgroupIds = asStringArray(subgroupIdOrIds);
|
|
79
84
|
this.transportOrder = ESPRMNeoBase.getTransportOrder();
|
|
80
85
|
this.availableTransports = {};
|
|
81
|
-
this.applyNodeConfig(config);
|
|
82
86
|
if (config.connectivity_status) {
|
|
83
87
|
this.connectivityStatus = config.connectivity_status;
|
|
84
88
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
type: ESPTransportMode.mqtt,
|
|
88
|
-
metadata: {},
|
|
89
|
-
});
|
|
90
|
-
}
|
|
89
|
+
this.applyNodeConfig(config);
|
|
90
|
+
this.syncMqttTransportAvailability();
|
|
91
91
|
this.subscribeToMqttUpdates();
|
|
92
92
|
}
|
|
93
93
|
/**
|
|
@@ -167,11 +167,14 @@ class ESPRMNeoNode {
|
|
|
167
167
|
this.devices = deviceRecords.map((d) => new ESPRMNeoDevice(transformNodeDevice(d), nodeRef));
|
|
168
168
|
this.services = serviceRecords.map((s) => new ESPRMNeoService(transformNodeService(s), nodeRef));
|
|
169
169
|
// Keep wire records for cache writes (never persist live class instances).
|
|
170
|
+
// Preserve last-known connectivity when the incoming config omits it
|
|
171
|
+
// (cloud node config does not include connectivity_status).
|
|
170
172
|
this.wireConfig = {
|
|
171
173
|
...config,
|
|
172
174
|
info,
|
|
173
175
|
devices: deviceRecords,
|
|
174
176
|
services: serviceRecords,
|
|
177
|
+
connectivity_status: config.connectivity_status ?? this.connectivityStatus,
|
|
175
178
|
};
|
|
176
179
|
this.config = {
|
|
177
180
|
...config,
|
|
@@ -241,19 +244,27 @@ class ESPRMNeoNode {
|
|
|
241
244
|
this.wireConfig.params = this.config.params;
|
|
242
245
|
}
|
|
243
246
|
this.applyConnectivityStatus(shadow, connectivityStatus);
|
|
244
|
-
|
|
247
|
+
this.persistWireConfig();
|
|
245
248
|
this.refreshConfigIfNcfgChanged(shadow);
|
|
246
249
|
}
|
|
247
250
|
/**
|
|
248
|
-
* Updates {@link connectivityStatus}
|
|
249
|
-
*
|
|
250
|
-
* an existing status is not cleared.
|
|
251
|
+
* Updates {@link connectivityStatus} when the shadow reports `online`, then
|
|
252
|
+
* syncs MQTT transport availability. Partial updates without `online` are
|
|
253
|
+
* ignored so an existing status is not cleared.
|
|
251
254
|
*/
|
|
252
255
|
applyConnectivityStatus(shadow, connectivityStatus) {
|
|
253
256
|
if (shadow.state?.reported?.online === undefined)
|
|
254
257
|
return;
|
|
255
258
|
this.connectivityStatus = connectivityStatus;
|
|
256
|
-
|
|
259
|
+
this.wireConfig.connectivity_status = connectivityStatus;
|
|
260
|
+
this.syncMqttTransportAvailability();
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Registers the MQTT transport only while {@link connectivityStatus} reports
|
|
264
|
+
* the node as connected; removes it when offline.
|
|
265
|
+
*/
|
|
266
|
+
syncMqttTransportAvailability() {
|
|
267
|
+
if (this.connectivityStatus.isConnected) {
|
|
257
268
|
this.addTransport(ESPTransportMode.mqtt, {
|
|
258
269
|
type: ESPTransportMode.mqtt,
|
|
259
270
|
metadata: {},
|
|
@@ -263,6 +274,14 @@ class ESPRMNeoNode {
|
|
|
263
274
|
this.removeTransport(ESPTransportMode.mqtt);
|
|
264
275
|
}
|
|
265
276
|
}
|
|
277
|
+
/** Persists {@link wireConfig} (including last-known connectivity) to storage. */
|
|
278
|
+
persistWireConfig() {
|
|
279
|
+
ESPRMNeoStorage.setItem(StorageKeys.NODE_CONFIG_PREFIX + this.nodeId, JSON.stringify({
|
|
280
|
+
...this.wireConfig,
|
|
281
|
+
node_id: this.nodeId,
|
|
282
|
+
connectivity_status: this.connectivityStatus,
|
|
283
|
+
}));
|
|
284
|
+
}
|
|
266
285
|
/** When cloud `ncfg_ver` changes, refetch config and persist the new marker. */
|
|
267
286
|
async refreshConfigIfNcfgChanged(shadow) {
|
|
268
287
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ESPRMNeoNode.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ESPRMNeoNode.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/esm/index.js
CHANGED
|
@@ -102,6 +102,8 @@ import './methods/ESPDevice/SetProofOfPossession.js';
|
|
|
102
102
|
import './methods/ESPDevice/SendData.js';
|
|
103
103
|
import './methods/ESPDevice/InitializeSession.js';
|
|
104
104
|
import './methods/ESPDevice/SetNetworkCredentials.js';
|
|
105
|
+
import './methods/ESPDevice/ResetWifiStatus.js';
|
|
106
|
+
import './methods/ESPDevice/RetryNetworkCredentials.js';
|
|
105
107
|
import './methods/ESPDevice/InitiateUserNodeMapping.js';
|
|
106
108
|
import './methods/ESPDevice/VerifyUserNodeMapping.js';
|
|
107
109
|
import './methods/ESPDevice/StartAssistedClaiming.js';
|
|
@@ -109,7 +111,7 @@ export { buildGroupControlParamsTopic, buildRainMakerUserParamsTopic, buildShado
|
|
|
109
111
|
export { coerceToFiniteNumber, coerceToNonEmptyString, coerceToString } from './utils/coerce.js';
|
|
110
112
|
export { buildCanonicalQueryString, createAuthorizationHeader, generateIotDeviceGatewayMqttSignedUrl, generateSigV4AuthHeader } from './utils/awsSigv4Utils.js';
|
|
111
113
|
export { buildMainApiUrl, buildUserCredentialsUrl, ensureValidIdToken, extractTemporaryCredentials, isExpiredTokenAuthError, parseCredentialsErrorMessage, postUserCredentials, refreshUserSession } from './utils/awsUtils.js';
|
|
112
|
-
export { APICallValidationErrorCodes, APIEndpoints, APIOperations, APIPathV1, AWSCredentialsErrorMessages, AuthErrorCodes, AuthSuccessMessages, AutomationStatusValues, AutomationSuccessMessages, CLAIM_CSR_MAX_CHUNKS, CLAIM_DEVICE_CSR_KEYS, CLAIM_DEVICE_MAC_KEYS, CLAIM_MAC_HEX_LENGTHS, CLAIM_MAC_SEPARATORS, CLAIM_MAX_FRAGMENT_SIZE, ClaimCapabilities, ClaimCapabilityPolicies, ClaimEndpoints, ClaimErrorCodes, ClaimProgressMessages, ConfigErrorCodes, DEFAULT_REST_API_VERSION, ESPProvProgressMessages, ESPRMNeoErrorCodes, ESPRMNeoStorageKeys, ESPServiceParamType, ESPServiceType, Endpoint, ErrorLabels, GroupSuccessMessages, GroupUserAliases, HTTPMethods, IntegrationSuccessMessages, NodeSuccessMessages, NodeWarnMessages, ProtocolType, ProvErrorCodes, ProvisionType, SDK_VERSION, ScheduleErrorMessages, ScheduleSuccessMessages, ServiceType, SharingSuccessMessages, StatusMessage, StorageAdapterErrorCodes, StorageKeys, SubscriptionChannelIds, TokenErrorCodes, TriggerErrorMessages, TriggerSuccessMessages, ValidationErrorCodes } from './utils/constants.js';
|
|
114
|
+
export { APICallValidationErrorCodes, APIEndpoints, APIOperations, APIPathV1, AWSCredentialsErrorMessages, AssumeRoleErrorMessages, AuthErrorCodes, AuthSuccessMessages, AutomationStatusValues, AutomationSuccessMessages, CLAIM_CSR_MAX_CHUNKS, CLAIM_DEVICE_CSR_KEYS, CLAIM_DEVICE_MAC_KEYS, CLAIM_MAC_HEX_LENGTHS, CLAIM_MAC_SEPARATORS, CLAIM_MAX_FRAGMENT_SIZE, ClaimCapabilities, ClaimCapabilityPolicies, ClaimEndpoints, ClaimErrorCodes, ClaimProgressMessages, ConfigErrorCodes, DEFAULT_REST_API_VERSION, ESPProvProgressMessages, ESPRMNeoErrorCodes, ESPRMNeoStorageKeys, ESPServiceParamType, ESPServiceType, Endpoint, ErrorLabels, GroupSuccessMessages, GroupUserAliases, HTTPMethods, IntegrationSuccessMessages, NodeSuccessMessages, NodeWarnMessages, ProtocolType, ProvErrorCodes, ProvisionType, SDK_VERSION, ScheduleErrorMessages, ScheduleSuccessMessages, ServiceType, SharingSuccessMessages, StatusMessage, StorageAdapterErrorCodes, StorageKeys, SubscriptionChannelIds, TokenErrorCodes, TriggerErrorMessages, TriggerSuccessMessages, ValidationErrorCodes } from './utils/constants.js';
|
|
113
115
|
export { LogLevel, Logger } from './utils/logger.js';
|
|
114
116
|
export { concurrentFetchPool } from './utils/mapLimit.js';
|
|
115
117
|
export { EventEmitter } from './utils/eventEmitter.js';
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -65,6 +65,13 @@ async function runChallengeResponseFlow(device, ssid, passphrase, groupId, onPro
|
|
|
65
65
|
challenge_response: signedChallenge,
|
|
66
66
|
node_id: nodeId,
|
|
67
67
|
});
|
|
68
|
+
// Association is verified and cannot be repeated; remember what step 6 needs
|
|
69
|
+
// so `retryNetworkCredentials` can resume from the Wi-Fi step.
|
|
70
|
+
device.provisionResumeState = {
|
|
71
|
+
nodeId: nodeId,
|
|
72
|
+
groupId,
|
|
73
|
+
options: options,
|
|
74
|
+
};
|
|
68
75
|
// 5. SET NETWORK CREDENTIALS
|
|
69
76
|
reportProgress(onProgress, ESPProvResponseStatus.onProgress, ESPProvProgressMessages.SETTING_NETWORK_CREDENTIALS);
|
|
70
77
|
await device.setNetworkCredentials(ssid, passphrase);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Provision.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Provision.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ESPDevice } from '../../ESPDevice.js';
|
|
2
|
+
import { Logger } from '../../utils/logger.js';
|
|
3
|
+
|
|
4
|
+
/*
|
|
5
|
+
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
|
6
|
+
*
|
|
7
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
8
|
+
*/
|
|
9
|
+
const logger = new Logger("ResetWifiStatus");
|
|
10
|
+
ESPDevice.prototype.resetWifiStatus = async function () {
|
|
11
|
+
if (!this.ESPProvisionAdapter.resetWifiStatus) {
|
|
12
|
+
logger.warn(`Adapter has no resetWifiStatus; treating as not acknowledged for "${this.name}"`);
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
try {
|
|
16
|
+
const acknowledged = await this.ESPProvisionAdapter.resetWifiStatus(this.name);
|
|
17
|
+
return acknowledged;
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
logger.error(`<- device "${this.name}": reset failed`, error);
|
|
21
|
+
throw error;
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=ResetWifiStatus.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ResetWifiStatus.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { ESPDevice } from '../../ESPDevice.js';
|
|
2
|
+
import { ESPProvResponseStatus } from '../../types/provision.js';
|
|
3
|
+
import { ESPProvProgressMessages } from '../../utils/constants.js';
|
|
4
|
+
import { ESPProvError } from '../../utils/error/ESPProvError.js';
|
|
5
|
+
import { waitForNodeOnline, DEFAULT_NODE_ONLINE_TIMEOUT_MS } from '../../utils/waitForNodeOnline.js';
|
|
6
|
+
import { Logger } from '../../utils/logger.js';
|
|
7
|
+
|
|
8
|
+
/*
|
|
9
|
+
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
|
10
|
+
*
|
|
11
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
12
|
+
*/
|
|
13
|
+
const logger = new Logger("RetryNetworkCredentials");
|
|
14
|
+
ESPDevice.prototype.retryNetworkCredentials = async function (ssid, passphrase, onProgress) {
|
|
15
|
+
const resumeState = this.provisionResumeState;
|
|
16
|
+
if (!resumeState) {
|
|
17
|
+
logger.error(`Retry refused for "${this.name}": no association recorded, nothing to resume`);
|
|
18
|
+
throw new ESPProvError("FAILED_PROV");
|
|
19
|
+
}
|
|
20
|
+
onProgress({
|
|
21
|
+
status: ESPProvResponseStatus.onProgress,
|
|
22
|
+
description: ESPProvProgressMessages.SETTING_NETWORK_CREDENTIALS,
|
|
23
|
+
});
|
|
24
|
+
await this.setNetworkCredentials(ssid, passphrase);
|
|
25
|
+
const options = resumeState.options;
|
|
26
|
+
if (options?.waitForOnline && options.user) {
|
|
27
|
+
onProgress({
|
|
28
|
+
status: ESPProvResponseStatus.onProgress,
|
|
29
|
+
description: ESPProvProgressMessages.WAITING_FOR_ONLINE,
|
|
30
|
+
});
|
|
31
|
+
await waitForNodeOnline({
|
|
32
|
+
nodeId: resumeState.nodeId,
|
|
33
|
+
groupId: resumeState.groupId,
|
|
34
|
+
user: options.user,
|
|
35
|
+
timeoutMs: options.onlineTimeoutMs ?? DEFAULT_NODE_ONLINE_TIMEOUT_MS,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
onProgress({
|
|
39
|
+
status: ESPProvResponseStatus.succeed,
|
|
40
|
+
description: resumeState.nodeId ?? ESPProvProgressMessages.DEVICE_PROVISIONED,
|
|
41
|
+
});
|
|
42
|
+
return resumeState.nodeId;
|
|
43
|
+
};
|
|
44
|
+
//# sourceMappingURL=RetryNetworkCredentials.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RetryNetworkCredentials.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -14,7 +14,10 @@ ESPRMNeoNode.prototype.sync = async function () {
|
|
|
14
14
|
// Apply first so a schema issue surfaces to the caller instead of
|
|
15
15
|
// poisoning the storage cache for the next cold start.
|
|
16
16
|
this.applyNodeConfig(config);
|
|
17
|
-
await writeLocalNodeConfig(this.nodeId,
|
|
17
|
+
await writeLocalNodeConfig(this.nodeId, {
|
|
18
|
+
...config,
|
|
19
|
+
connectivity_status: this.connectivityStatus,
|
|
20
|
+
});
|
|
18
21
|
return this;
|
|
19
22
|
}
|
|
20
23
|
catch (error) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Sync.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Sync.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ESPRMNeoUser } from '../../../ESPRMNeoUser.js';
|
|
2
|
-
import { APIPathV1 } from '../../../utils/constants.js';
|
|
2
|
+
import { AssumeRoleErrorMessages, APIPathV1 } from '../../../utils/constants.js';
|
|
3
3
|
import { ESPSigV4APIManager } from '../../../services/ESPSigV4APIManager.js';
|
|
4
4
|
|
|
5
5
|
/*
|
|
@@ -9,27 +9,26 @@ import { ESPSigV4APIManager } from '../../../services/ESPSigV4APIManager.js';
|
|
|
9
9
|
*/
|
|
10
10
|
/**
|
|
11
11
|
* Implementation of the `assumeRole` method for the `ESPRMNeoUser` class.
|
|
12
|
-
*
|
|
13
|
-
* Exchanges identity (temporary) credentials for assume-role credentials with IoT/MQTT
|
|
14
|
-
* permissions. The backend signs the user in with the provided credentials and returns
|
|
15
|
-
* a new credential set for MQTT; this is not refreshing or extending the same credentials.
|
|
16
12
|
*/
|
|
17
13
|
ESPRMNeoUser.prototype.assumeRole = async function (accessKey, secretKey, sessionToken, options) {
|
|
18
|
-
// Request body: identity (temporary) credentials so backend can assume the IoT role
|
|
19
14
|
const requestBody = {
|
|
20
15
|
access_key: accessKey,
|
|
21
16
|
secret_key: secretKey,
|
|
22
17
|
session_token: sessionToken,
|
|
23
18
|
};
|
|
24
|
-
|
|
25
|
-
if (
|
|
26
|
-
|
|
19
|
+
const servicesMode = !!(options?.services && options.services.length > 0);
|
|
20
|
+
if (servicesMode) {
|
|
21
|
+
if (!options.nodeId) {
|
|
22
|
+
throw new Error(AssumeRoleErrorMessages.NODE_ID_REQUIRED);
|
|
23
|
+
}
|
|
24
|
+
requestBody.services = options.services;
|
|
25
|
+
requestBody.node_id = options.nodeId;
|
|
27
26
|
}
|
|
28
27
|
const api = ESPSigV4APIManager.getInstance();
|
|
29
28
|
const response = await api.post(APIPathV1.ASSUME_ROLE, requestBody);
|
|
30
29
|
// Validate response contains required fields
|
|
31
30
|
if (!response.access_key || !response.secret_key || !response.session_token) {
|
|
32
|
-
throw new Error(
|
|
31
|
+
throw new Error(AssumeRoleErrorMessages.INVALID_RESPONSE);
|
|
33
32
|
}
|
|
34
33
|
return response;
|
|
35
34
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AssumeRole.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"AssumeRole.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"esp_rmaker_chal_resp.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"esp_rmaker_chal_resp.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -85,6 +85,19 @@ class ESPRMNeoMqtt {
|
|
|
85
85
|
isConnected() {
|
|
86
86
|
return this.#adapter.isConnected();
|
|
87
87
|
}
|
|
88
|
+
/**
|
|
89
|
+
* Registers a transport connection-status listener when the underlying
|
|
90
|
+
* adapter supports it; otherwise returns a no-op unsubscribe.
|
|
91
|
+
*
|
|
92
|
+
* @param callback - Invoked with `{ connected }` on status changes
|
|
93
|
+
* @returns Unsubscribe function
|
|
94
|
+
*/
|
|
95
|
+
onConnectionStatusChange(callback) {
|
|
96
|
+
if (typeof this.#adapter.onConnectionStatusChange === "function") {
|
|
97
|
+
return this.#adapter.onConnectionStatusChange(callback);
|
|
98
|
+
}
|
|
99
|
+
return () => { };
|
|
100
|
+
}
|
|
88
101
|
/**
|
|
89
102
|
* Publish a message to a topic.
|
|
90
103
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ESPRMNeoMqtt.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ESPRMNeoMqtt.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -139,8 +139,8 @@ class NodeMQTTOrchestrator {
|
|
|
139
139
|
/**
|
|
140
140
|
* Registers a node with the orchestrator.
|
|
141
141
|
* Must be called before subscribeToNode, getParams, getShadow, etc.
|
|
142
|
-
* On shadow rename: clears the old binding
|
|
143
|
-
*
|
|
142
|
+
* On shadow rename: clears the old binding, then installs the new name
|
|
143
|
+
* (including shrinks to a shorter membership shadow).
|
|
144
144
|
*
|
|
145
145
|
* @param nodeId - The device/node identifier.
|
|
146
146
|
* @param shadowName - The named shadow (e.g. `params-groupId-subgroupId`).
|
|
@@ -149,9 +149,6 @@ class NodeMQTTOrchestrator {
|
|
|
149
149
|
const instance = NodeMQTTOrchestrator.getInstance();
|
|
150
150
|
const existing = instance.nodeMap.get(nodeId);
|
|
151
151
|
if (existing && existing.shadowName !== shadowName) {
|
|
152
|
-
if (shadowName.split("-").length < existing.shadowName.split("-").length) {
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
152
|
NodeMQTTOrchestrator.unregisterNode(nodeId);
|
|
156
153
|
}
|
|
157
154
|
instance.nodeMap.set(nodeId, { shadowName });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NodeMQTTOrchestrator.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"NodeMQTTOrchestrator.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -391,6 +391,15 @@ const TriggerErrorMessages = {
|
|
|
391
391
|
/** Logged when retrieving triggers for a node fails. */
|
|
392
392
|
GET_FAILED: "getTriggers failed",
|
|
393
393
|
};
|
|
394
|
+
/**
|
|
395
|
+
* Error messages for assumeRole (POST /v1/assumed-roles).
|
|
396
|
+
*/
|
|
397
|
+
const AssumeRoleErrorMessages = {
|
|
398
|
+
/** Thrown when `services` is provided without a `nodeId`. */
|
|
399
|
+
NODE_ID_REQUIRED: "assumeRole: nodeId is required when services is provided",
|
|
400
|
+
/** Thrown when the assume-role response is missing required credential fields. */
|
|
401
|
+
INVALID_RESPONSE: "Invalid assume role response: missing required credential fields",
|
|
402
|
+
};
|
|
394
403
|
/**
|
|
395
404
|
* Error / log messages for temporary AWS credentials (POST /v1/user/credentials).
|
|
396
405
|
*/
|
|
@@ -840,5 +849,5 @@ const SubscriptionChannelIds = {
|
|
|
840
849
|
MQTT: "mqtt",
|
|
841
850
|
};
|
|
842
851
|
|
|
843
|
-
export { APICallValidationErrorCodes, APIEndpoints, APIOperations, APIPathV1, AWSCredentialsErrorMessages, AuthErrorCodes, AuthSuccessMessages, AutomationStatusValues, AutomationSuccessMessages, CLAIM_CSR_MAX_CHUNKS, CLAIM_DEVICE_CSR_KEYS, CLAIM_DEVICE_MAC_KEYS, CLAIM_MAC_HEX_LENGTHS, CLAIM_MAC_SEPARATORS, CLAIM_MAX_FRAGMENT_SIZE, ClaimCapabilities, ClaimCapabilityPolicies, ClaimEndpoints, ClaimErrorCodes, ClaimProgressMessages, ConfigErrorCodes, DEFAULT_REST_API_VERSION, ESPProvProgressMessages, ESPRMNeoErrorCodes, ESPRMNeoStorageKeys, ESPServiceParamType, ESPServiceType, Endpoint, ErrorLabels, GroupSuccessMessages, GroupUserAliases, HTTPMethods, IntegrationSuccessMessages, NodeSuccessMessages, NodeWarnMessages, ProtocolType, ProvErrorCodes, ProvisionType, SDK_VERSION, ScheduleErrorMessages, ScheduleSuccessMessages, ServiceType, SharingSuccessMessages, StatusMessage, StorageAdapterErrorCodes, StorageKeys, SubscriptionChannelIds, TokenErrorCodes, TriggerErrorMessages, TriggerSuccessMessages, ValidationErrorCodes };
|
|
852
|
+
export { APICallValidationErrorCodes, APIEndpoints, APIOperations, APIPathV1, AWSCredentialsErrorMessages, AssumeRoleErrorMessages, AuthErrorCodes, AuthSuccessMessages, AutomationStatusValues, AutomationSuccessMessages, CLAIM_CSR_MAX_CHUNKS, CLAIM_DEVICE_CSR_KEYS, CLAIM_DEVICE_MAC_KEYS, CLAIM_MAC_HEX_LENGTHS, CLAIM_MAC_SEPARATORS, CLAIM_MAX_FRAGMENT_SIZE, ClaimCapabilities, ClaimCapabilityPolicies, ClaimEndpoints, ClaimErrorCodes, ClaimProgressMessages, ConfigErrorCodes, DEFAULT_REST_API_VERSION, ESPProvProgressMessages, ESPRMNeoErrorCodes, ESPRMNeoStorageKeys, ESPServiceParamType, ESPServiceType, Endpoint, ErrorLabels, GroupSuccessMessages, GroupUserAliases, HTTPMethods, IntegrationSuccessMessages, NodeSuccessMessages, NodeWarnMessages, ProtocolType, ProvErrorCodes, ProvisionType, SDK_VERSION, ScheduleErrorMessages, ScheduleSuccessMessages, ServiceType, SharingSuccessMessages, StatusMessage, StorageAdapterErrorCodes, StorageKeys, SubscriptionChannelIds, TokenErrorCodes, TriggerErrorMessages, TriggerSuccessMessages, ValidationErrorCodes };
|
|
844
853
|
//# sourceMappingURL=constants.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"constants.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -26,7 +26,18 @@ async function readLocalNodeConfig(nodeId) {
|
|
|
26
26
|
/** Best-effort persist of node config to local storage. */
|
|
27
27
|
async function writeLocalNodeConfig(nodeId, config) {
|
|
28
28
|
try {
|
|
29
|
-
|
|
29
|
+
let toStore = config;
|
|
30
|
+
// Cloud config omits connectivity — keep the last cached status when writing.
|
|
31
|
+
if (!config.connectivity_status) {
|
|
32
|
+
const prev = await ESPRMNeoStorage.getNodeConfig(nodeId);
|
|
33
|
+
if (prev?.connectivity_status) {
|
|
34
|
+
toStore = {
|
|
35
|
+
...config,
|
|
36
|
+
connectivity_status: prev.connectivity_status,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
await ESPRMNeoStorage.setNodeConfig(nodeId, toStore);
|
|
30
41
|
}
|
|
31
42
|
catch (error) {
|
|
32
43
|
logger.warn(`Cache write failed for ${nodeId}`, error);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nodeUtils.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"nodeUtils.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -63,11 +63,12 @@ function isNodeOnlineFromShadowPayload(payload) {
|
|
|
63
63
|
* @throws {ESPProvError} If `timeoutMs` elapses without the node reporting online.
|
|
64
64
|
* @throws {Error} If MQTT connection or subscription fails.
|
|
65
65
|
*/
|
|
66
|
-
async function waitForNodeOnline({ nodeId, groupId, user, timeoutMs = DEFAULT_NODE_ONLINE_TIMEOUT_MS, pollIntervalMs = DEFAULT_NODE_ONLINE_POLL_INTERVAL_MS, }) {
|
|
67
|
-
const shadowName = constructShadowName(groupId);
|
|
66
|
+
async function waitForNodeOnline({ nodeId, groupId, subgroupIds, user, timeoutMs = DEFAULT_NODE_ONLINE_TIMEOUT_MS, pollIntervalMs = DEFAULT_NODE_ONLINE_POLL_INTERVAL_MS, }) {
|
|
67
|
+
const shadowName = constructShadowName(groupId, subgroupIds ?? []);
|
|
68
68
|
logger.info("Waiting for node to come online", {
|
|
69
69
|
nodeId,
|
|
70
70
|
groupId,
|
|
71
|
+
subgroupIds: subgroupIds ?? [],
|
|
71
72
|
shadowName,
|
|
72
73
|
timeoutMs,
|
|
73
74
|
pollIntervalMs,
|
|
@@ -147,10 +148,10 @@ async function waitForNodeOnline({ nodeId, groupId, user, timeoutMs = DEFAULT_NO
|
|
|
147
148
|
});
|
|
148
149
|
await user.connectMQTT();
|
|
149
150
|
}
|
|
150
|
-
// 2.
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
151
|
+
// 2. Bind to the membership shadow and subscribe before the shadow may exist.
|
|
152
|
+
// Always registerNode so a leftover longer/stale binding for the same nodeId
|
|
153
|
+
// is rebound to constructShadowName(groupId, subgroupIds).
|
|
154
|
+
NodeMQTTOrchestrator.registerNode(nodeId, shadowName);
|
|
154
155
|
await NodeMQTTOrchestrator.subscribeToNode(nodeId, onUpdate);
|
|
155
156
|
logger.debug("Subscribed to node shadow for online wait", {
|
|
156
157
|
nodeId,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"waitForNodeOnline.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"waitForNodeOnline.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -9,5 +9,15 @@ export declare class ESPDevice implements ESPDeviceInterface {
|
|
|
9
9
|
name: string;
|
|
10
10
|
transport: string;
|
|
11
11
|
security: number;
|
|
12
|
+
/**
|
|
13
|
+
* What a completed association produced, kept so `retryNetworkCredentials`
|
|
14
|
+
* can resume the flow instead of repeating it. Set once verification
|
|
15
|
+
* succeeds; `undefined` until then.
|
|
16
|
+
*/
|
|
17
|
+
provisionResumeState?: {
|
|
18
|
+
nodeId: string;
|
|
19
|
+
groupId: string;
|
|
20
|
+
options?: Record<string, any>;
|
|
21
|
+
};
|
|
12
22
|
constructor(deviceConfig: ESPDeviceInterface);
|
|
13
23
|
}
|
|
@@ -22,11 +22,16 @@ export declare class ESPRMNeoNode {
|
|
|
22
22
|
subgroupIds: string[];
|
|
23
23
|
devices: ESPRMNeoDevice[];
|
|
24
24
|
services: ESPRMNeoService[];
|
|
25
|
+
/**
|
|
26
|
+
* Last-known connectivity. Seeded from cached `connectivity_status` when
|
|
27
|
+
* present (cloud config does not provide it); otherwise starts offline until
|
|
28
|
+
* an MQTT shadow `online` update arrives.
|
|
29
|
+
*/
|
|
25
30
|
connectivityStatus: ESPRMNeoConnectivityStatusInterface;
|
|
26
31
|
/**
|
|
27
32
|
* Transports currently usable for this node, keyed by mode.
|
|
28
|
-
* - `mqtt` (cloud) is added when the node
|
|
29
|
-
*
|
|
33
|
+
* - `mqtt` (cloud) is added when the node is connected and removed when it
|
|
34
|
+
* goes offline (from cached `connectivity_status` or shadow updates).
|
|
30
35
|
* - `local` is added/removed at runtime by a `localDiscovery` subscriber as the
|
|
31
36
|
* node appears/disappears on the LAN (via {@link addTransport}/{@link removeTransport}).
|
|
32
37
|
* Apps may also add custom string-keyed entries (pair with
|
|
@@ -132,11 +137,18 @@ export declare class ESPRMNeoNode {
|
|
|
132
137
|
*/
|
|
133
138
|
private processNodeUpdate;
|
|
134
139
|
/**
|
|
135
|
-
* Updates {@link connectivityStatus}
|
|
136
|
-
*
|
|
137
|
-
* an existing status is not cleared.
|
|
140
|
+
* Updates {@link connectivityStatus} when the shadow reports `online`, then
|
|
141
|
+
* syncs MQTT transport availability. Partial updates without `online` are
|
|
142
|
+
* ignored so an existing status is not cleared.
|
|
138
143
|
*/
|
|
139
144
|
private applyConnectivityStatus;
|
|
145
|
+
/**
|
|
146
|
+
* Registers the MQTT transport only while {@link connectivityStatus} reports
|
|
147
|
+
* the node as connected; removes it when offline.
|
|
148
|
+
*/
|
|
149
|
+
private syncMqttTransportAvailability;
|
|
150
|
+
/** Persists {@link wireConfig} (including last-known connectivity) to storage. */
|
|
151
|
+
private persistWireConfig;
|
|
140
152
|
/** When cloud `ncfg_ver` changes, refetch config and persist the new marker. */
|
|
141
153
|
private refreshConfigIfNcfgChanged;
|
|
142
154
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Augments the ESPDevice class with the `resetWifiStatus` method.
|
|
3
|
+
*/
|
|
4
|
+
declare module "../../ESPDevice" {
|
|
5
|
+
interface ESPDevice {
|
|
6
|
+
/**
|
|
7
|
+
* Asks the device to clear its Wi-Fi state over the open provisioning session.
|
|
8
|
+
*
|
|
9
|
+
* Sent on the network-control endpoint, so it needs an established session and
|
|
10
|
+
* leaves the user-node association intact — only Wi-Fi credentials are cleared.
|
|
11
|
+
* That is what makes `retryNetworkCredentials` possible after a wrong password,
|
|
12
|
+
* instead of making the user factory reset the board.
|
|
13
|
+
* @returns A promise resolving to `true` when the device acknowledged the reset.
|
|
14
|
+
*/
|
|
15
|
+
resetWifiStatus(): Promise<boolean>;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { ESPProvResponse } from "../../types/provision";
|
|
2
|
+
/**
|
|
3
|
+
* Augments the ESPDevice class with the `retryNetworkCredentials` method.
|
|
4
|
+
*/
|
|
5
|
+
declare module "../../ESPDevice" {
|
|
6
|
+
interface ESPDevice {
|
|
7
|
+
/**
|
|
8
|
+
* Re-sends Wi-Fi credentials after `resetWifiStatus`, resuming the flow the
|
|
9
|
+
* first attempt started rather than repeating its association.
|
|
10
|
+
*
|
|
11
|
+
* Sending credentials alone is not enough: the online wait and the success
|
|
12
|
+
* report follow them and need the node id the association produced, which
|
|
13
|
+
* only this SDK holds.
|
|
14
|
+
* @param ssid - The SSID, unchanged from the first attempt.
|
|
15
|
+
* @param passphrase - The corrected Wi-Fi password.
|
|
16
|
+
* @param onProgress - Progress callback; emits the same messages as `provision`.
|
|
17
|
+
* @returns A promise resolving to the node id.
|
|
18
|
+
* @throws {ESPProvError} When no association has completed on this device yet.
|
|
19
|
+
*/
|
|
20
|
+
retryNetworkCredentials(ssid: string, passphrase: string, onProgress: (message: ESPProvResponse) => void): Promise<string>;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -8,6 +8,8 @@ import "./SetProofOfPossession";
|
|
|
8
8
|
import "./SendData";
|
|
9
9
|
import "./InitializeSession";
|
|
10
10
|
import "./SetNetworkCredentials";
|
|
11
|
+
import "./ResetWifiStatus";
|
|
12
|
+
import "./RetryNetworkCredentials";
|
|
11
13
|
import "./InitiateUserNodeMapping";
|
|
12
14
|
import "./VerifyUserNodeMapping";
|
|
13
15
|
import "./StartAssistedClaiming";
|