@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/LICENSE
CHANGED
|
@@ -187,7 +187,7 @@
|
|
|
187
187
|
same "printed page" as the copyright notice for easier
|
|
188
188
|
identification within third-party archives.
|
|
189
189
|
|
|
190
|
-
Copyright 2026 Espressif Systems
|
|
190
|
+
Copyright 2026 Espressif Systems (Shanghai) CO LTD
|
|
191
191
|
|
|
192
192
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
193
193
|
you may not use this file except in compliance with the License.
|
package/README.md
CHANGED
|
@@ -1,3 +1,40 @@
|
|
|
1
|
+
# ESP RainMaker Neo - IoT Cloud
|
|
2
|
+
|
|
3
|
+
**Tools**
|
|
4
|
+
|
|
5
|
+
[](https://espressif.github.io/esp-launchpad/?flashConfigURL=https://espressif.github.io/esp-rainmaker-neo-firmware/launchpad.toml)
|
|
6
|
+
|
|
7
|
+
[](https://apps.apple.com/us/app/esp-rainmaker-home/id1563728960)
|
|
8
|
+
|
|
9
|
+
[](https://play.google.com/store/apps/details?id=com.espressif.novahome)
|
|
10
|
+
|
|
11
|
+
**Documentation**
|
|
12
|
+
|
|
13
|
+
[](https://neo.rainmaker.espressif.com)
|
|
14
|
+
|
|
15
|
+
[](https://docs.neo.rainmaker.espressif.com/)
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Introduction
|
|
20
|
+
|
|
21
|
+
ESP RainMaker Neo is a serverless, open-source IoT cloud for ESP devices that you deploy into your own AWS account. It scales with your fleet and is pay-as-you-go. Devices connect over MQTT through AWS IoT. Phone apps, the admin dashboard and voice assistants reach the same backend over REST APIs and MQTT.
|
|
22
|
+
|
|
23
|
+
<p align="center">
|
|
24
|
+
<img src="assets/images/architecture.svg" alt="ESP RainMaker Neo Architecture" width="800">
|
|
25
|
+
</p>
|
|
26
|
+
|
|
27
|
+
### Repositories
|
|
28
|
+
|
|
29
|
+
| Repository | Holds |
|
|
30
|
+
| ------------------------------------------------------------------------------------- | ------------------------------------------------ |
|
|
31
|
+
| [esp-rainmaker-neo](https://github.com/espressif/esp-rainmaker-neo) | Cloud backend, admin dashboard |
|
|
32
|
+
| [esp-rainmaker-neo-firmware](https://github.com/espressif/esp-rainmaker-neo-firmware) | Device firmware SDK |
|
|
33
|
+
| [esp-rainmaker-home](https://github.com/espressif/esp-rainmaker-home)<br>[esp-rainmaker-neo-app-sdk-ts](https://github.com/espressif/esp-rainmaker-neo-app-sdk-ts) | ESP RainMaker Home phone app (iOS and Android)<br>(this repository) ESP RainMaker Neo App SDK (TypeScript) |
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
1
38
|
# ESP RainMaker Neo TypeScript SDK
|
|
2
39
|
|
|
3
40
|
**RainMaker Neo** (short: **RMNeo**) is Espressif’s AIoT stack. `@espressif/rainmaker-neo-base-sdk` is the TypeScript SDK that powers JavaScript-based apps integrating with RainMaker Neo — authentication, groups/nodes, device provisioning, real-time MQTT control, and group sharing.
|
|
@@ -63,10 +100,7 @@ import { ESPRMNeoBase } from "@espressif/rainmaker-neo-base-sdk";
|
|
|
63
100
|
ESPRMNeoBase.init({
|
|
64
101
|
baseUrl: "https://your-api-gateway.amazonaws.com/prod",
|
|
65
102
|
userApiBase: "https://your-user-api-gateway.amazonaws.com/prod",
|
|
66
|
-
identityId: "your-identity-pool-id",
|
|
67
103
|
awsRegion: "us-east-1",
|
|
68
|
-
userPoolId: "your-user-pool-id",
|
|
69
|
-
clientId: "your-cognito-client-id",
|
|
70
104
|
iotEndpoint: "xxxxxxxx-ats.iot.us-east-1.amazonaws.com",
|
|
71
105
|
// Optional adapters (provided by your app):
|
|
72
106
|
// mqttAdapter, customStorageAdapter, provisionAdapter, ...
|
|
@@ -184,7 +218,9 @@ await device.disconnect();
|
|
|
184
218
|
|
|
185
219
|
## API Documentation
|
|
186
220
|
|
|
187
|
-
|
|
221
|
+
Browse the hosted API reference at [https://espressif.github.io/esp-rainmaker-neo-app-sdk-ts/](https://espressif.github.io/esp-rainmaker-neo-app-sdk-ts/).
|
|
222
|
+
|
|
223
|
+
To generate local docs from JSDoc:
|
|
188
224
|
|
|
189
225
|
```bash
|
|
190
226
|
npm run genDocs
|
package/dist/cjs/ESPDevice.js
CHANGED
|
@@ -24,6 +24,12 @@ class ESPDevice {
|
|
|
24
24
|
name;
|
|
25
25
|
transport;
|
|
26
26
|
security;
|
|
27
|
+
/**
|
|
28
|
+
* What a completed association produced, kept so `retryNetworkCredentials`
|
|
29
|
+
* can resume the flow instead of repeating it. Set once verification
|
|
30
|
+
* succeeds; `undefined` until then.
|
|
31
|
+
*/
|
|
32
|
+
provisionResumeState;
|
|
27
33
|
constructor(deviceConfig) {
|
|
28
34
|
this.name = deviceConfig.name;
|
|
29
35
|
this.transport = deviceConfig.transport;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ESPDevice.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ESPDevice.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/cjs/ESPRMNeoNode.js
CHANGED
|
@@ -40,14 +40,19 @@ class ESPRMNeoNode {
|
|
|
40
40
|
subgroupIds = [];
|
|
41
41
|
devices = [];
|
|
42
42
|
services = [];
|
|
43
|
+
/**
|
|
44
|
+
* Last-known connectivity. Seeded from cached `connectivity_status` when
|
|
45
|
+
* present (cloud config does not provide it); otherwise starts offline until
|
|
46
|
+
* an MQTT shadow `online` update arrives.
|
|
47
|
+
*/
|
|
43
48
|
connectivityStatus = {
|
|
44
49
|
isConnected: false,
|
|
45
50
|
lastConnectionTimestamp: 0,
|
|
46
51
|
};
|
|
47
52
|
/**
|
|
48
53
|
* Transports currently usable for this node, keyed by mode.
|
|
49
|
-
* - `mqtt` (cloud) is added when the node
|
|
50
|
-
*
|
|
54
|
+
* - `mqtt` (cloud) is added when the node is connected and removed when it
|
|
55
|
+
* goes offline (from cached `connectivity_status` or shadow updates).
|
|
51
56
|
* - `local` is added/removed at runtime by a `localDiscovery` subscriber as the
|
|
52
57
|
* node appears/disappears on the LAN (via {@link addTransport}/{@link removeTransport}).
|
|
53
58
|
* Apps may also add custom string-keyed entries (pair with
|
|
@@ -80,16 +85,11 @@ class ESPRMNeoNode {
|
|
|
80
85
|
this.subgroupIds = common.asStringArray(subgroupIdOrIds);
|
|
81
86
|
this.transportOrder = ESPRMNeoBase.ESPRMNeoBase.getTransportOrder();
|
|
82
87
|
this.availableTransports = {};
|
|
83
|
-
this.applyNodeConfig(config);
|
|
84
88
|
if (config.connectivity_status) {
|
|
85
89
|
this.connectivityStatus = config.connectivity_status;
|
|
86
90
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
type: transport.ESPTransportMode.mqtt,
|
|
90
|
-
metadata: {},
|
|
91
|
-
});
|
|
92
|
-
}
|
|
91
|
+
this.applyNodeConfig(config);
|
|
92
|
+
this.syncMqttTransportAvailability();
|
|
93
93
|
this.subscribeToMqttUpdates();
|
|
94
94
|
}
|
|
95
95
|
/**
|
|
@@ -169,11 +169,14 @@ class ESPRMNeoNode {
|
|
|
169
169
|
this.devices = deviceRecords.map((d) => new ESPRMNeoDevice.ESPRMNeoDevice(nodeTransform.transformNodeDevice(d), nodeRef));
|
|
170
170
|
this.services = serviceRecords.map((s) => new ESPRMNeoService.ESPRMNeoService(nodeTransform.transformNodeService(s), nodeRef));
|
|
171
171
|
// Keep wire records for cache writes (never persist live class instances).
|
|
172
|
+
// Preserve last-known connectivity when the incoming config omits it
|
|
173
|
+
// (cloud node config does not include connectivity_status).
|
|
172
174
|
this.wireConfig = {
|
|
173
175
|
...config,
|
|
174
176
|
info,
|
|
175
177
|
devices: deviceRecords,
|
|
176
178
|
services: serviceRecords,
|
|
179
|
+
connectivity_status: config.connectivity_status ?? this.connectivityStatus,
|
|
177
180
|
};
|
|
178
181
|
this.config = {
|
|
179
182
|
...config,
|
|
@@ -243,19 +246,27 @@ class ESPRMNeoNode {
|
|
|
243
246
|
this.wireConfig.params = this.config.params;
|
|
244
247
|
}
|
|
245
248
|
this.applyConnectivityStatus(shadow, connectivityStatus);
|
|
246
|
-
|
|
249
|
+
this.persistWireConfig();
|
|
247
250
|
this.refreshConfigIfNcfgChanged(shadow);
|
|
248
251
|
}
|
|
249
252
|
/**
|
|
250
|
-
* Updates {@link connectivityStatus}
|
|
251
|
-
*
|
|
252
|
-
* an existing status is not cleared.
|
|
253
|
+
* Updates {@link connectivityStatus} when the shadow reports `online`, then
|
|
254
|
+
* syncs MQTT transport availability. Partial updates without `online` are
|
|
255
|
+
* ignored so an existing status is not cleared.
|
|
253
256
|
*/
|
|
254
257
|
applyConnectivityStatus(shadow, connectivityStatus) {
|
|
255
258
|
if (shadow.state?.reported?.online === undefined)
|
|
256
259
|
return;
|
|
257
260
|
this.connectivityStatus = connectivityStatus;
|
|
258
|
-
|
|
261
|
+
this.wireConfig.connectivity_status = connectivityStatus;
|
|
262
|
+
this.syncMqttTransportAvailability();
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Registers the MQTT transport only while {@link connectivityStatus} reports
|
|
266
|
+
* the node as connected; removes it when offline.
|
|
267
|
+
*/
|
|
268
|
+
syncMqttTransportAvailability() {
|
|
269
|
+
if (this.connectivityStatus.isConnected) {
|
|
259
270
|
this.addTransport(transport.ESPTransportMode.mqtt, {
|
|
260
271
|
type: transport.ESPTransportMode.mqtt,
|
|
261
272
|
metadata: {},
|
|
@@ -265,6 +276,14 @@ class ESPRMNeoNode {
|
|
|
265
276
|
this.removeTransport(transport.ESPTransportMode.mqtt);
|
|
266
277
|
}
|
|
267
278
|
}
|
|
279
|
+
/** Persists {@link wireConfig} (including last-known connectivity) to storage. */
|
|
280
|
+
persistWireConfig() {
|
|
281
|
+
ESPRMNeoStorage.ESPRMNeoStorage.setItem(constants.StorageKeys.NODE_CONFIG_PREFIX + this.nodeId, JSON.stringify({
|
|
282
|
+
...this.wireConfig,
|
|
283
|
+
node_id: this.nodeId,
|
|
284
|
+
connectivity_status: this.connectivityStatus,
|
|
285
|
+
}));
|
|
286
|
+
}
|
|
268
287
|
/** When cloud `ncfg_ver` changes, refetch config and persist the new marker. */
|
|
269
288
|
async refreshConfigIfNcfgChanged(shadow) {
|
|
270
289
|
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/cjs/index.js
CHANGED
|
@@ -104,6 +104,8 @@ require('./methods/ESPDevice/SetProofOfPossession.js');
|
|
|
104
104
|
require('./methods/ESPDevice/SendData.js');
|
|
105
105
|
require('./methods/ESPDevice/InitializeSession.js');
|
|
106
106
|
require('./methods/ESPDevice/SetNetworkCredentials.js');
|
|
107
|
+
require('./methods/ESPDevice/ResetWifiStatus.js');
|
|
108
|
+
require('./methods/ESPDevice/RetryNetworkCredentials.js');
|
|
107
109
|
require('./methods/ESPDevice/InitiateUserNodeMapping.js');
|
|
108
110
|
require('./methods/ESPDevice/VerifyUserNodeMapping.js');
|
|
109
111
|
require('./methods/ESPDevice/StartAssistedClaiming.js');
|
|
@@ -224,6 +226,7 @@ exports.APIEndpoints = constants.APIEndpoints;
|
|
|
224
226
|
exports.APIOperations = constants.APIOperations;
|
|
225
227
|
exports.APIPathV1 = constants.APIPathV1;
|
|
226
228
|
exports.AWSCredentialsErrorMessages = constants.AWSCredentialsErrorMessages;
|
|
229
|
+
exports.AssumeRoleErrorMessages = constants.AssumeRoleErrorMessages;
|
|
227
230
|
exports.AuthErrorCodes = constants.AuthErrorCodes;
|
|
228
231
|
exports.AuthSuccessMessages = constants.AuthSuccessMessages;
|
|
229
232
|
exports.AutomationStatusValues = constants.AutomationStatusValues;
|
package/dist/cjs/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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -67,6 +67,13 @@ async function runChallengeResponseFlow(device, ssid, passphrase, groupId, onPro
|
|
|
67
67
|
challenge_response: signedChallenge,
|
|
68
68
|
node_id: nodeId,
|
|
69
69
|
});
|
|
70
|
+
// Association is verified and cannot be repeated; remember what step 6 needs
|
|
71
|
+
// so `retryNetworkCredentials` can resume from the Wi-Fi step.
|
|
72
|
+
device.provisionResumeState = {
|
|
73
|
+
nodeId: nodeId,
|
|
74
|
+
groupId,
|
|
75
|
+
options: options,
|
|
76
|
+
};
|
|
70
77
|
// 5. SET NETWORK CREDENTIALS
|
|
71
78
|
reportProgress(onProgress, provision.ESPProvResponseStatus.onProgress, constants.ESPProvProgressMessages.SETTING_NETWORK_CREDENTIALS);
|
|
72
79
|
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,26 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var ESPDevice = require('../../ESPDevice.js');
|
|
4
|
+
var logger$1 = require('../../utils/logger.js');
|
|
5
|
+
|
|
6
|
+
/*
|
|
7
|
+
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
|
8
|
+
*
|
|
9
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
10
|
+
*/
|
|
11
|
+
const logger = new logger$1.Logger("ResetWifiStatus");
|
|
12
|
+
ESPDevice.ESPDevice.prototype.resetWifiStatus = async function () {
|
|
13
|
+
if (!this.ESPProvisionAdapter.resetWifiStatus) {
|
|
14
|
+
logger.warn(`Adapter has no resetWifiStatus; treating as not acknowledged for "${this.name}"`);
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
try {
|
|
18
|
+
const acknowledged = await this.ESPProvisionAdapter.resetWifiStatus(this.name);
|
|
19
|
+
return acknowledged;
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
logger.error(`<- device "${this.name}": reset failed`, error);
|
|
23
|
+
throw error;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=ResetWifiStatus.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ResetWifiStatus.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var ESPDevice = require('../../ESPDevice.js');
|
|
4
|
+
var provision = require('../../types/provision.js');
|
|
5
|
+
var constants = require('../../utils/constants.js');
|
|
6
|
+
var ESPProvError = require('../../utils/error/ESPProvError.js');
|
|
7
|
+
var waitForNodeOnline = require('../../utils/waitForNodeOnline.js');
|
|
8
|
+
var logger$1 = require('../../utils/logger.js');
|
|
9
|
+
|
|
10
|
+
/*
|
|
11
|
+
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
|
12
|
+
*
|
|
13
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
14
|
+
*/
|
|
15
|
+
const logger = new logger$1.Logger("RetryNetworkCredentials");
|
|
16
|
+
ESPDevice.ESPDevice.prototype.retryNetworkCredentials = async function (ssid, passphrase, onProgress) {
|
|
17
|
+
const resumeState = this.provisionResumeState;
|
|
18
|
+
if (!resumeState) {
|
|
19
|
+
logger.error(`Retry refused for "${this.name}": no association recorded, nothing to resume`);
|
|
20
|
+
throw new ESPProvError.ESPProvError("FAILED_PROV");
|
|
21
|
+
}
|
|
22
|
+
onProgress({
|
|
23
|
+
status: provision.ESPProvResponseStatus.onProgress,
|
|
24
|
+
description: constants.ESPProvProgressMessages.SETTING_NETWORK_CREDENTIALS,
|
|
25
|
+
});
|
|
26
|
+
await this.setNetworkCredentials(ssid, passphrase);
|
|
27
|
+
const options = resumeState.options;
|
|
28
|
+
if (options?.waitForOnline && options.user) {
|
|
29
|
+
onProgress({
|
|
30
|
+
status: provision.ESPProvResponseStatus.onProgress,
|
|
31
|
+
description: constants.ESPProvProgressMessages.WAITING_FOR_ONLINE,
|
|
32
|
+
});
|
|
33
|
+
await waitForNodeOnline.waitForNodeOnline({
|
|
34
|
+
nodeId: resumeState.nodeId,
|
|
35
|
+
groupId: resumeState.groupId,
|
|
36
|
+
user: options.user,
|
|
37
|
+
timeoutMs: options.onlineTimeoutMs ?? waitForNodeOnline.DEFAULT_NODE_ONLINE_TIMEOUT_MS,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
onProgress({
|
|
41
|
+
status: provision.ESPProvResponseStatus.succeed,
|
|
42
|
+
description: resumeState.nodeId ?? constants.ESPProvProgressMessages.DEVICE_PROVISIONED,
|
|
43
|
+
});
|
|
44
|
+
return resumeState.nodeId;
|
|
45
|
+
};
|
|
46
|
+
//# sourceMappingURL=RetryNetworkCredentials.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RetryNetworkCredentials.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -16,7 +16,10 @@ ESPRMNeoNode.ESPRMNeoNode.prototype.sync = async function () {
|
|
|
16
16
|
// Apply first so a schema issue surfaces to the caller instead of
|
|
17
17
|
// poisoning the storage cache for the next cold start.
|
|
18
18
|
this.applyNodeConfig(config);
|
|
19
|
-
await nodeUtils.writeLocalNodeConfig(this.nodeId,
|
|
19
|
+
await nodeUtils.writeLocalNodeConfig(this.nodeId, {
|
|
20
|
+
...config,
|
|
21
|
+
connectivity_status: this.connectivityStatus,
|
|
22
|
+
});
|
|
20
23
|
return this;
|
|
21
24
|
}
|
|
22
25
|
catch (error) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Sync.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Sync.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -11,27 +11,26 @@ var ESPSigV4APIManager = require('../../../services/ESPSigV4APIManager.js');
|
|
|
11
11
|
*/
|
|
12
12
|
/**
|
|
13
13
|
* Implementation of the `assumeRole` method for the `ESPRMNeoUser` class.
|
|
14
|
-
*
|
|
15
|
-
* Exchanges identity (temporary) credentials for assume-role credentials with IoT/MQTT
|
|
16
|
-
* permissions. The backend signs the user in with the provided credentials and returns
|
|
17
|
-
* a new credential set for MQTT; this is not refreshing or extending the same credentials.
|
|
18
14
|
*/
|
|
19
15
|
ESPRMNeoUser.ESPRMNeoUser.prototype.assumeRole = async function (accessKey, secretKey, sessionToken, options) {
|
|
20
|
-
// Request body: identity (temporary) credentials so backend can assume the IoT role
|
|
21
16
|
const requestBody = {
|
|
22
17
|
access_key: accessKey,
|
|
23
18
|
secret_key: secretKey,
|
|
24
19
|
session_token: sessionToken,
|
|
25
20
|
};
|
|
26
|
-
|
|
27
|
-
if (
|
|
28
|
-
|
|
21
|
+
const servicesMode = !!(options?.services && options.services.length > 0);
|
|
22
|
+
if (servicesMode) {
|
|
23
|
+
if (!options.nodeId) {
|
|
24
|
+
throw new Error(constants.AssumeRoleErrorMessages.NODE_ID_REQUIRED);
|
|
25
|
+
}
|
|
26
|
+
requestBody.services = options.services;
|
|
27
|
+
requestBody.node_id = options.nodeId;
|
|
29
28
|
}
|
|
30
29
|
const api = ESPSigV4APIManager.ESPSigV4APIManager.getInstance();
|
|
31
30
|
const response = await api.post(constants.APIPathV1.ASSUME_ROLE, requestBody);
|
|
32
31
|
// Validate response contains required fields
|
|
33
32
|
if (!response.access_key || !response.secret_key || !response.session_token) {
|
|
34
|
-
throw new Error(
|
|
33
|
+
throw new Error(constants.AssumeRoleErrorMessages.INVALID_RESPONSE);
|
|
35
34
|
}
|
|
36
35
|
return response;
|
|
37
36
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AssumeRole.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"AssumeRole.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -21,6 +21,11 @@ function _interopNamespaceDefault(e) {
|
|
|
21
21
|
|
|
22
22
|
var pb_1__namespace = /*#__PURE__*/_interopNamespaceDefault(pb_1);
|
|
23
23
|
|
|
24
|
+
/*
|
|
25
|
+
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
|
26
|
+
*
|
|
27
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
28
|
+
*/
|
|
24
29
|
/**
|
|
25
30
|
* Generated by the protoc-gen-ts. DO NOT EDIT!
|
|
26
31
|
* compiler version: 5.29.3
|
|
@@ -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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -87,6 +87,19 @@ class ESPRMNeoMqtt {
|
|
|
87
87
|
isConnected() {
|
|
88
88
|
return this.#adapter.isConnected();
|
|
89
89
|
}
|
|
90
|
+
/**
|
|
91
|
+
* Registers a transport connection-status listener when the underlying
|
|
92
|
+
* adapter supports it; otherwise returns a no-op unsubscribe.
|
|
93
|
+
*
|
|
94
|
+
* @param callback - Invoked with `{ connected }` on status changes
|
|
95
|
+
* @returns Unsubscribe function
|
|
96
|
+
*/
|
|
97
|
+
onConnectionStatusChange(callback) {
|
|
98
|
+
if (typeof this.#adapter.onConnectionStatusChange === "function") {
|
|
99
|
+
return this.#adapter.onConnectionStatusChange(callback);
|
|
100
|
+
}
|
|
101
|
+
return () => { };
|
|
102
|
+
}
|
|
90
103
|
/**
|
|
91
104
|
* Publish a message to a topic.
|
|
92
105
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ESPRMNeoMqtt.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ESPRMNeoMqtt.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -141,8 +141,8 @@ class NodeMQTTOrchestrator {
|
|
|
141
141
|
/**
|
|
142
142
|
* Registers a node with the orchestrator.
|
|
143
143
|
* Must be called before subscribeToNode, getParams, getShadow, etc.
|
|
144
|
-
* On shadow rename: clears the old binding
|
|
145
|
-
*
|
|
144
|
+
* On shadow rename: clears the old binding, then installs the new name
|
|
145
|
+
* (including shrinks to a shorter membership shadow).
|
|
146
146
|
*
|
|
147
147
|
* @param nodeId - The device/node identifier.
|
|
148
148
|
* @param shadowName - The named shadow (e.g. `params-groupId-subgroupId`).
|
|
@@ -151,9 +151,6 @@ class NodeMQTTOrchestrator {
|
|
|
151
151
|
const instance = NodeMQTTOrchestrator.getInstance();
|
|
152
152
|
const existing = instance.nodeMap.get(nodeId);
|
|
153
153
|
if (existing && existing.shadowName !== shadowName) {
|
|
154
|
-
if (shadowName.split("-").length < existing.shadowName.split("-").length) {
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
157
154
|
NodeMQTTOrchestrator.unregisterNode(nodeId);
|
|
158
155
|
}
|
|
159
156
|
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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -393,6 +393,15 @@ const TriggerErrorMessages = {
|
|
|
393
393
|
/** Logged when retrieving triggers for a node fails. */
|
|
394
394
|
GET_FAILED: "getTriggers failed",
|
|
395
395
|
};
|
|
396
|
+
/**
|
|
397
|
+
* Error messages for assumeRole (POST /v1/assumed-roles).
|
|
398
|
+
*/
|
|
399
|
+
const AssumeRoleErrorMessages = {
|
|
400
|
+
/** Thrown when `services` is provided without a `nodeId`. */
|
|
401
|
+
NODE_ID_REQUIRED: "assumeRole: nodeId is required when services is provided",
|
|
402
|
+
/** Thrown when the assume-role response is missing required credential fields. */
|
|
403
|
+
INVALID_RESPONSE: "Invalid assume role response: missing required credential fields",
|
|
404
|
+
};
|
|
396
405
|
/**
|
|
397
406
|
* Error / log messages for temporary AWS credentials (POST /v1/user/credentials).
|
|
398
407
|
*/
|
|
@@ -847,6 +856,7 @@ exports.APIEndpoints = APIEndpoints;
|
|
|
847
856
|
exports.APIOperations = APIOperations;
|
|
848
857
|
exports.APIPathV1 = APIPathV1;
|
|
849
858
|
exports.AWSCredentialsErrorMessages = AWSCredentialsErrorMessages;
|
|
859
|
+
exports.AssumeRoleErrorMessages = AssumeRoleErrorMessages;
|
|
850
860
|
exports.AuthErrorCodes = AuthErrorCodes;
|
|
851
861
|
exports.AuthSuccessMessages = AuthSuccessMessages;
|
|
852
862
|
exports.AutomationStatusValues = AutomationStatusValues;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"constants.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -28,7 +28,18 @@ async function readLocalNodeConfig(nodeId) {
|
|
|
28
28
|
/** Best-effort persist of node config to local storage. */
|
|
29
29
|
async function writeLocalNodeConfig(nodeId, config) {
|
|
30
30
|
try {
|
|
31
|
-
|
|
31
|
+
let toStore = config;
|
|
32
|
+
// Cloud config omits connectivity — keep the last cached status when writing.
|
|
33
|
+
if (!config.connectivity_status) {
|
|
34
|
+
const prev = await ESPRMNeoStorage.ESPRMNeoStorage.getNodeConfig(nodeId);
|
|
35
|
+
if (prev?.connectivity_status) {
|
|
36
|
+
toStore = {
|
|
37
|
+
...config,
|
|
38
|
+
connectivity_status: prev.connectivity_status,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
await ESPRMNeoStorage.ESPRMNeoStorage.setNodeConfig(nodeId, toStore);
|
|
32
43
|
}
|
|
33
44
|
catch (error) {
|
|
34
45
|
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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -65,11 +65,12 @@ function isNodeOnlineFromShadowPayload(payload) {
|
|
|
65
65
|
* @throws {ESPProvError} If `timeoutMs` elapses without the node reporting online.
|
|
66
66
|
* @throws {Error} If MQTT connection or subscription fails.
|
|
67
67
|
*/
|
|
68
|
-
async function waitForNodeOnline({ nodeId, groupId, user, timeoutMs = DEFAULT_NODE_ONLINE_TIMEOUT_MS, pollIntervalMs = DEFAULT_NODE_ONLINE_POLL_INTERVAL_MS, }) {
|
|
69
|
-
const shadowName = shadowUtils.constructShadowName(groupId);
|
|
68
|
+
async function waitForNodeOnline({ nodeId, groupId, subgroupIds, user, timeoutMs = DEFAULT_NODE_ONLINE_TIMEOUT_MS, pollIntervalMs = DEFAULT_NODE_ONLINE_POLL_INTERVAL_MS, }) {
|
|
69
|
+
const shadowName = shadowUtils.constructShadowName(groupId, subgroupIds ?? []);
|
|
70
70
|
logger.info("Waiting for node to come online", {
|
|
71
71
|
nodeId,
|
|
72
72
|
groupId,
|
|
73
|
+
subgroupIds: subgroupIds ?? [],
|
|
73
74
|
shadowName,
|
|
74
75
|
timeoutMs,
|
|
75
76
|
pollIntervalMs,
|
|
@@ -149,10 +150,10 @@ async function waitForNodeOnline({ nodeId, groupId, user, timeoutMs = DEFAULT_NO
|
|
|
149
150
|
});
|
|
150
151
|
await user.connectMQTT();
|
|
151
152
|
}
|
|
152
|
-
// 2.
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
153
|
+
// 2. Bind to the membership shadow and subscribe before the shadow may exist.
|
|
154
|
+
// Always registerNode so a leftover longer/stale binding for the same nodeId
|
|
155
|
+
// is rebound to constructShadowName(groupId, subgroupIds).
|
|
156
|
+
NodeMQTTOrchestrator.NodeMQTTOrchestrator.registerNode(nodeId, shadowName);
|
|
156
157
|
await NodeMQTTOrchestrator.NodeMQTTOrchestrator.subscribeToNode(nodeId, onUpdate);
|
|
157
158
|
logger.debug("Subscribed to node shadow for online wait", {
|
|
158
159
|
nodeId,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"waitForNodeOnline.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"waitForNodeOnline.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/esm/ESPDevice.js
CHANGED
|
@@ -22,6 +22,12 @@ class ESPDevice {
|
|
|
22
22
|
name;
|
|
23
23
|
transport;
|
|
24
24
|
security;
|
|
25
|
+
/**
|
|
26
|
+
* What a completed association produced, kept so `retryNetworkCredentials`
|
|
27
|
+
* can resume the flow instead of repeating it. Set once verification
|
|
28
|
+
* succeeds; `undefined` until then.
|
|
29
|
+
*/
|
|
30
|
+
provisionResumeState;
|
|
25
31
|
constructor(deviceConfig) {
|
|
26
32
|
this.name = deviceConfig.name;
|
|
27
33
|
this.transport = deviceConfig.transport;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ESPDevice.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ESPDevice.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|