@espressif/rainmaker-neo-base-sdk 1.0.0 → 1.2.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/ESPRMNeoBase.js +1 -1
- package/dist/cjs/ESPRMNeoNode.js +33 -14
- package/dist/cjs/ESPRMNeoNode.js.map +1 -1
- package/dist/cjs/index.js +14 -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/proto/rmaker_local_ctrl.js +273 -0
- package/dist/cjs/proto/rmaker_local_ctrl.js.map +1 -0
- package/dist/cjs/services/ESPRMNeoMqtt/ESPRMNeoMqtt.js +13 -0
- package/dist/cjs/services/ESPRMNeoMqtt/ESPRMNeoMqtt.js.map +1 -1
- package/dist/cjs/services/ESPTransport/ESPDiscovery/ESPDiscoveryManager.js +5 -4
- package/dist/cjs/services/ESPTransport/ESPDiscovery/ESPDiscoveryManager.js.map +1 -1
- package/dist/cjs/services/ESPTransport/ESPLocalControlTransport.js +183 -116
- package/dist/cjs/services/ESPTransport/ESPLocalControlTransport.js.map +1 -1
- package/dist/cjs/services/ESPTransport/LocalControlSession.js +62 -0
- package/dist/cjs/services/ESPTransport/LocalControlSession.js.map +1 -0
- package/dist/cjs/services/NodeMQTTOrchestrator.js +2 -5
- package/dist/cjs/services/NodeMQTTOrchestrator.js.map +1 -1
- package/dist/cjs/types/transport.js +24 -0
- package/dist/cjs/types/transport.js.map +1 -1
- package/dist/cjs/utils/constants.js +80 -4
- package/dist/cjs/utils/constants.js.map +1 -1
- package/dist/cjs/utils/eventSubscriptionUtils.js +48 -4
- package/dist/cjs/utils/eventSubscriptionUtils.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/ESPRMNeoBase.js +1 -1
- package/dist/esm/ESPRMNeoNode.js +33 -14
- package/dist/esm/ESPRMNeoNode.js.map +1 -1
- package/dist/esm/index.js +4 -2
- 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/proto/rmaker_local_ctrl.js +271 -0
- package/dist/esm/proto/rmaker_local_ctrl.js.map +1 -0
- package/dist/esm/services/ESPRMNeoMqtt/ESPRMNeoMqtt.js +13 -0
- package/dist/esm/services/ESPRMNeoMqtt/ESPRMNeoMqtt.js.map +1 -1
- package/dist/esm/services/ESPTransport/ESPDiscovery/ESPDiscoveryManager.js +5 -4
- package/dist/esm/services/ESPTransport/ESPDiscovery/ESPDiscoveryManager.js.map +1 -1
- package/dist/esm/services/ESPTransport/ESPLocalControlTransport.js +184 -117
- package/dist/esm/services/ESPTransport/ESPLocalControlTransport.js.map +1 -1
- package/dist/esm/services/ESPTransport/LocalControlSession.js +59 -0
- package/dist/esm/services/ESPTransport/LocalControlSession.js.map +1 -0
- package/dist/esm/services/NodeMQTTOrchestrator.js +2 -5
- package/dist/esm/services/NodeMQTTOrchestrator.js.map +1 -1
- package/dist/esm/types/transport.js +24 -1
- package/dist/esm/types/transport.js.map +1 -1
- package/dist/esm/utils/constants.js +74 -5
- package/dist/esm/utils/constants.js.map +1 -1
- package/dist/esm/utils/eventSubscriptionUtils.js +49 -5
- package/dist/esm/utils/eventSubscriptionUtils.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/ESPRMNeoBase.d.ts +1 -1
- 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/proto/rmaker_local_ctrl.d.ts +137 -0
- package/dist/types/services/ESPRMNeoMqtt/ESPRMNeoMqtt.d.ts +10 -0
- package/dist/types/services/ESPTransport/ESPDiscovery/ESPDiscoveryManager.d.ts +4 -3
- package/dist/types/services/ESPTransport/ESPLocalControlTransport.d.ts +70 -23
- package/dist/types/services/ESPTransport/LocalControlSession.d.ts +24 -0
- package/dist/types/services/NodeMQTTOrchestrator.d.ts +2 -2
- package/dist/types/services/interfaces/MQTTTransport.d.ts +10 -0
- package/dist/types/types/discovery.d.ts +1 -1
- package/dist/types/types/localControl.d.ts +26 -1
- package/dist/types/types/provision.d.ts +10 -0
- package/dist/types/types/transport.d.ts +24 -2
- package/dist/types/utils/baseUtils.d.ts +1 -1
- package/dist/types/utils/constants.d.ts +74 -5
- package/dist/types/utils/eventSubscriptionUtils.d.ts +19 -3
- package/dist/types/utils/waitForNodeOnline.d.ts +9 -3
- package/package.json +1 -1
- package/dist/cjs/proto/constants.js +0 -24
- package/dist/cjs/proto/constants.js.map +0 -1
- package/dist/cjs/proto/esp_local_ctrl.js +0 -787
- package/dist/cjs/proto/esp_local_ctrl.js.map +0 -1
- package/dist/esm/proto/constants.js +0 -24
- package/dist/esm/proto/constants.js.map +0 -1
- package/dist/esm/proto/esp_local_ctrl.js +0 -758
- package/dist/esm/proto/esp_local_ctrl.js.map +0 -1
- package/dist/types/proto/constants.d.ts +0 -15
- package/dist/types/proto/esp_local_ctrl.d.ts +0 -283
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ESPLocalControlTransport.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ESPLocalControlTransport.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var ESPRMNeoBase = require('../../ESPRMNeoBase.js');
|
|
4
|
+
|
|
5
|
+
/*
|
|
6
|
+
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
|
7
|
+
*
|
|
8
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
9
|
+
*/
|
|
10
|
+
/** Attempts made before a local-control handshake is reported as failed. */
|
|
11
|
+
const DEFAULT_CONNECT_RETRIES = 3;
|
|
12
|
+
/**
|
|
13
|
+
* Returns the app-supplied local control adapter.
|
|
14
|
+
*
|
|
15
|
+
* @throws {Error} When no adapter was registered on {@link ESPRMNeoBase}.
|
|
16
|
+
*/
|
|
17
|
+
function getLocalControlAdapter() {
|
|
18
|
+
const adapter = ESPRMNeoBase.ESPRMNeoBase.getLocalControlAdapter();
|
|
19
|
+
if (!adapter) {
|
|
20
|
+
throw new Error("Local control adapter is not configured");
|
|
21
|
+
}
|
|
22
|
+
return adapter;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Ensures a usable local-control session for `nodeId`, connecting (with
|
|
26
|
+
* retries) when the adapter reports none.
|
|
27
|
+
*
|
|
28
|
+
* The adapter resolves on a successful handshake and rejects otherwise, so a
|
|
29
|
+
* resolved `connect` is treated as connected.
|
|
30
|
+
*
|
|
31
|
+
* @param adapter - Adapter to drive.
|
|
32
|
+
* @param nodeId - Node to connect to.
|
|
33
|
+
* @param metadata - Local transport metadata (`baseUrl`, `securityType`, `pop`,
|
|
34
|
+
* `username`).
|
|
35
|
+
* @param options - Session endpoints for the protocol in use; omitted for the
|
|
36
|
+
* adapter's built-in default paths.
|
|
37
|
+
* @param maxRetries - Connection attempts before failing.
|
|
38
|
+
* @throws {Error} When every connection attempt fails.
|
|
39
|
+
*/
|
|
40
|
+
async function ensureLocalControlSession(adapter, nodeId, metadata, options, maxRetries = DEFAULT_CONNECT_RETRIES) {
|
|
41
|
+
if (await adapter.isConnected(nodeId)) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
let attempt = 0;
|
|
45
|
+
let lastError;
|
|
46
|
+
while (attempt < maxRetries) {
|
|
47
|
+
try {
|
|
48
|
+
await adapter.connect(nodeId, metadata.baseUrl, metadata.securityType ?? 0, metadata.pop, metadata.username, options);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
lastError = error;
|
|
53
|
+
attempt += 1;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const message = lastError instanceof Error ? lastError.message : String(lastError);
|
|
57
|
+
throw new Error(`Failed to connect after ${maxRetries} attempts: ${message}`);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
exports.ensureLocalControlSession = ensureLocalControlSession;
|
|
61
|
+
exports.getLocalControlAdapter = getLocalControlAdapter;
|
|
62
|
+
//# sourceMappingURL=LocalControlSession.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LocalControlSession.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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -19,6 +19,29 @@ exports.ESPTransportMode = void 0;
|
|
|
19
19
|
/** Communication is routed through MQTT (RainMaker Neo cloud: AWS shadow). */
|
|
20
20
|
ESPTransportMode["mqtt"] = "mqtt";
|
|
21
21
|
})(exports.ESPTransportMode || (exports.ESPTransportMode = {}));
|
|
22
|
+
/**
|
|
23
|
+
* Wire protocol spoken by the `local` transport. Both protocols run over a
|
|
24
|
+
* protocomm session on the node's LAN HTTP server; they differ in endpoint
|
|
25
|
+
* names and message encoding.
|
|
26
|
+
*
|
|
27
|
+
* Carried on the local transport config's `metadata.protocol`, set by local
|
|
28
|
+
* discovery from the mDNS service type that produced the hit.
|
|
29
|
+
*/
|
|
30
|
+
exports.ESPLocalControlProtocol = void 0;
|
|
31
|
+
(function (ESPLocalControlProtocol) {
|
|
32
|
+
/**
|
|
33
|
+
* RainMaker Neo protocol (`rmaker_local_ctrl/*` session plus
|
|
34
|
+
* `get_params`/`set_params`/`get_config`), advertised as
|
|
35
|
+
* `_esp_rmaker_ctrl._tcp`. Default for this SDK.
|
|
36
|
+
*/
|
|
37
|
+
ESPLocalControlProtocol["rmakerLocalCtrl"] = "rmaker_local_ctrl";
|
|
38
|
+
})(exports.ESPLocalControlProtocol || (exports.ESPLocalControlProtocol = {}));
|
|
39
|
+
/**
|
|
40
|
+
* Protocol assumed when a local transport config carries no explicit
|
|
41
|
+
* `metadata.protocol` — for example a LAN transport restored from a client-side
|
|
42
|
+
* registry rather than a fresh discovery hit.
|
|
43
|
+
*/
|
|
44
|
+
const DEFAULT_LOCAL_CONTROL_PROTOCOL = exports.ESPLocalControlProtocol.rmakerLocalCtrl;
|
|
22
45
|
/**
|
|
23
46
|
* Default transport priority order used when neither the node nor the SDK base
|
|
24
47
|
* has an explicit order configured: local control first, MQTT (cloud) fallback.
|
|
@@ -28,5 +51,6 @@ const DEFAULT_TRANSPORT_ORDER = [
|
|
|
28
51
|
exports.ESPTransportMode.mqtt,
|
|
29
52
|
];
|
|
30
53
|
|
|
54
|
+
exports.DEFAULT_LOCAL_CONTROL_PROTOCOL = DEFAULT_LOCAL_CONTROL_PROTOCOL;
|
|
31
55
|
exports.DEFAULT_TRANSPORT_ORDER = DEFAULT_TRANSPORT_ORDER;
|
|
32
56
|
//# sourceMappingURL=transport.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transport.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"transport.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
|
*/
|
|
@@ -466,8 +475,6 @@ const ProvisionType = {
|
|
|
466
475
|
* An object containing endpoint paths.
|
|
467
476
|
*/
|
|
468
477
|
const Endpoint = {
|
|
469
|
-
/** The endpoint for local control. */
|
|
470
|
-
LOCAL_CTRL: "esp_local_ctrl/control",
|
|
471
478
|
/** The endpoint for cloud user association. */
|
|
472
479
|
CLOUD_USER_ASSOCIATION: "cloud_user_assoc",
|
|
473
480
|
/** The endpoint for challenge-response and get-node-id protocol with the device. */
|
|
@@ -475,6 +482,64 @@ const Endpoint = {
|
|
|
475
482
|
/** The endpoint for assisted claiming. */
|
|
476
483
|
RM_CLAIM: "rmaker_claim",
|
|
477
484
|
};
|
|
485
|
+
/**
|
|
486
|
+
* Endpoint paths of the `rmaker_local_ctrl` protocol served by RainMaker Neo
|
|
487
|
+
* firmware (see the firmware's local-control endpoint protocol spec).
|
|
488
|
+
*
|
|
489
|
+
* All data endpoints inherit the security of the session established on
|
|
490
|
+
* {@link RMakerLocalCtrlEndpoint.SESSION}.
|
|
491
|
+
*/
|
|
492
|
+
const RMakerLocalCtrlEndpoint = {
|
|
493
|
+
/** Protocomm session-security endpoint (SEC1 with/without PoP, or SEC2). */
|
|
494
|
+
SESSION: "rmaker_local_ctrl/session",
|
|
495
|
+
/** POST any payload; responds with the service info JSON (`sec_ver`, `cap`, …). */
|
|
496
|
+
VERSION: "rmaker_local_ctrl/version",
|
|
497
|
+
/** Reads the params JSON — protobuf `CmdGetData`, fragmented response. */
|
|
498
|
+
GET_PARAMS: "get_params",
|
|
499
|
+
/** Reads the node config JSON — protobuf `CmdGetData`, fragmented response. */
|
|
500
|
+
GET_CONFIG: "get_config",
|
|
501
|
+
/** Writes params — raw JSON request and response (no protobuf). */
|
|
502
|
+
SET_PARAMS: "set_params",
|
|
503
|
+
};
|
|
504
|
+
/**
|
|
505
|
+
* Root key of the JSON served by {@link RMakerLocalCtrlEndpoint.VERSION}, i.e.
|
|
506
|
+
* `{"rmaker_local_ctrl": {"ver": …, "sec_ver": …, "cap": [...]}}`. Passed to the
|
|
507
|
+
* local-control adapter so the native layer probes the right scheme version.
|
|
508
|
+
*/
|
|
509
|
+
const RMAKER_LOCAL_CTRL_VERSION_KEY = "rmaker_local_ctrl";
|
|
510
|
+
/**
|
|
511
|
+
* Maximum fragment size (bytes) the firmware serves per `RespGetData`. Reads
|
|
512
|
+
* loop with `Offset += Payload.length` until `TotalLen` is reached; this value
|
|
513
|
+
* is informational (the device dictates the actual fragment length).
|
|
514
|
+
*/
|
|
515
|
+
const RMAKER_LOCAL_CTRL_FRAGMENT_SIZE = 200;
|
|
516
|
+
/**
|
|
517
|
+
* `status` values in a `set_params` raw-JSON response.
|
|
518
|
+
*/
|
|
519
|
+
const RMakerLocalCtrlSetParamsStatus = {
|
|
520
|
+
SUCCESS: "success",
|
|
521
|
+
FAIL: "fail",
|
|
522
|
+
};
|
|
523
|
+
/**
|
|
524
|
+
* mDNS TXT record keys advertised by the `_esp_rmaker_ctrl._tcp` service.
|
|
525
|
+
*/
|
|
526
|
+
const RMakerLocalCtrlTxtKey = {
|
|
527
|
+
/** Node ID (also the service instance name and hostname). */
|
|
528
|
+
NODE_ID: "node_id",
|
|
529
|
+
/** Comma-separated active capabilities — see {@link RMakerLocalCtrlCapability}. */
|
|
530
|
+
CAP: "cap",
|
|
531
|
+
};
|
|
532
|
+
/**
|
|
533
|
+
* Capability tokens found in the `cap` TXT record. A node advertising only
|
|
534
|
+
* `ch_resp` is reachable for on-network user-node association but *not* for
|
|
535
|
+
* param control, so it must not be registered as a local control transport.
|
|
536
|
+
*/
|
|
537
|
+
const RMakerLocalCtrlCapability = {
|
|
538
|
+
/** Params/config endpoints are registered. */
|
|
539
|
+
LOCAL_CTRL: "local_ctrl",
|
|
540
|
+
/** Challenge-response (on-network user-node association) is registered. */
|
|
541
|
+
CH_RESP: "ch_resp",
|
|
542
|
+
};
|
|
478
543
|
/**
|
|
479
544
|
* Assisted-claiming REST paths, on the deployment's main API and SigV4-signed
|
|
480
545
|
* like every other `/v1/*` route.
|
|
@@ -632,8 +697,12 @@ const ProvErrorCodes = {
|
|
|
632
697
|
* @enum {string}
|
|
633
698
|
*/
|
|
634
699
|
const ServiceType = {
|
|
635
|
-
/**
|
|
636
|
-
|
|
700
|
+
/**
|
|
701
|
+
* Service type advertised by RainMaker Neo firmware. A single instance serves
|
|
702
|
+
* the `rmaker_local_ctrl` endpoints; the `cap` TXT record says which endpoint
|
|
703
|
+
* sets are active. This is the default for local discovery in this SDK.
|
|
704
|
+
*/
|
|
705
|
+
ESP_RMAKER_LOCAL_CTRL_TCP: "_esp_rmaker_ctrl._tcp.",
|
|
637
706
|
};
|
|
638
707
|
/**
|
|
639
708
|
* An object containing protocol types.
|
|
@@ -847,6 +916,7 @@ exports.APIEndpoints = APIEndpoints;
|
|
|
847
916
|
exports.APIOperations = APIOperations;
|
|
848
917
|
exports.APIPathV1 = APIPathV1;
|
|
849
918
|
exports.AWSCredentialsErrorMessages = AWSCredentialsErrorMessages;
|
|
919
|
+
exports.AssumeRoleErrorMessages = AssumeRoleErrorMessages;
|
|
850
920
|
exports.AuthErrorCodes = AuthErrorCodes;
|
|
851
921
|
exports.AuthSuccessMessages = AuthSuccessMessages;
|
|
852
922
|
exports.AutomationStatusValues = AutomationStatusValues;
|
|
@@ -877,6 +947,12 @@ exports.NodeWarnMessages = NodeWarnMessages;
|
|
|
877
947
|
exports.ProtocolType = ProtocolType;
|
|
878
948
|
exports.ProvErrorCodes = ProvErrorCodes;
|
|
879
949
|
exports.ProvisionType = ProvisionType;
|
|
950
|
+
exports.RMAKER_LOCAL_CTRL_FRAGMENT_SIZE = RMAKER_LOCAL_CTRL_FRAGMENT_SIZE;
|
|
951
|
+
exports.RMAKER_LOCAL_CTRL_VERSION_KEY = RMAKER_LOCAL_CTRL_VERSION_KEY;
|
|
952
|
+
exports.RMakerLocalCtrlCapability = RMakerLocalCtrlCapability;
|
|
953
|
+
exports.RMakerLocalCtrlEndpoint = RMakerLocalCtrlEndpoint;
|
|
954
|
+
exports.RMakerLocalCtrlSetParamsStatus = RMakerLocalCtrlSetParamsStatus;
|
|
955
|
+
exports.RMakerLocalCtrlTxtKey = RMakerLocalCtrlTxtKey;
|
|
880
956
|
exports.SDK_VERSION = SDK_VERSION;
|
|
881
957
|
exports.ScheduleErrorMessages = ScheduleErrorMessages;
|
|
882
958
|
exports.ScheduleSuccessMessages = ScheduleSuccessMessages;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"constants.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -3,26 +3,70 @@
|
|
|
3
3
|
var ESPDiscoveryManager = require('../services/ESPTransport/ESPDiscovery/ESPDiscoveryManager.js');
|
|
4
4
|
var NodeUpdatesBus = require('../services/NodeUpdatesBus.js');
|
|
5
5
|
var transport = require('../types/transport.js');
|
|
6
|
+
var constants = require('./constants.js');
|
|
6
7
|
|
|
7
8
|
/*
|
|
8
9
|
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
|
9
10
|
*
|
|
10
11
|
* SPDX-License-Identifier: Apache-2.0
|
|
11
12
|
*/
|
|
12
|
-
/**
|
|
13
|
+
/**
|
|
14
|
+
* Splits the mDNS `cap` TXT record (`"local_ctrl,ch_resp"`) into tokens.
|
|
15
|
+
* Returns `undefined` when the record is absent, which older firmware omits.
|
|
16
|
+
*/
|
|
17
|
+
function parseCapabilities(txt) {
|
|
18
|
+
const raw = txt?.[constants.RMakerLocalCtrlTxtKey.CAP];
|
|
19
|
+
if (typeof raw !== "string")
|
|
20
|
+
return undefined;
|
|
21
|
+
const capabilities = raw
|
|
22
|
+
.split(",")
|
|
23
|
+
.map((capability) => capability.trim())
|
|
24
|
+
.filter(Boolean);
|
|
25
|
+
return capabilities.length ? capabilities : undefined;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Maps a default local-discovery hit into the client-facing payload shape.
|
|
29
|
+
*
|
|
30
|
+
* The `_esp_rmaker_ctrl._tcp` instance is also advertised by nodes that
|
|
31
|
+
* only serve challenge-response (on-network user-node association). Those are
|
|
32
|
+
* not reachable for param control, so a hit whose `cap` TXT record excludes
|
|
33
|
+
* `local_ctrl` maps to `undefined` and is dropped rather than registered as a
|
|
34
|
+
* local transport. A hit with no `cap` record is treated as control-capable.
|
|
35
|
+
*
|
|
36
|
+
* @param info - Raw adapter result (`nodeId`, `baseUrl`, and `txt` when the
|
|
37
|
+
* platform resolved TXT records).
|
|
38
|
+
* @returns The payload to deliver, or `undefined` to skip this hit.
|
|
39
|
+
*/
|
|
13
40
|
function toDiscoveredNodeData(info) {
|
|
41
|
+
const capabilities = parseCapabilities(info.txt);
|
|
42
|
+
if (capabilities &&
|
|
43
|
+
!capabilities.includes(constants.RMakerLocalCtrlCapability.LOCAL_CTRL)) {
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
14
46
|
return {
|
|
15
47
|
nodeId: info.nodeId,
|
|
16
48
|
transportDetails: {
|
|
17
49
|
type: transport.ESPTransportMode.local,
|
|
18
|
-
metadata: {
|
|
50
|
+
metadata: {
|
|
51
|
+
baseUrl: info.baseUrl,
|
|
52
|
+
protocol: transport.ESPLocalControlProtocol.rmakerLocalCtrl,
|
|
53
|
+
...(capabilities && { capabilities }),
|
|
54
|
+
},
|
|
19
55
|
},
|
|
20
56
|
};
|
|
21
57
|
}
|
|
22
|
-
/**
|
|
58
|
+
/**
|
|
59
|
+
* Starts LAN discovery; each hit is mapped then passed to `onDiscovered`.
|
|
60
|
+
* Hits that are not control-capable (see {@link toDiscoveredNodeData}) are
|
|
61
|
+
* skipped.
|
|
62
|
+
*/
|
|
23
63
|
function startLocalDiscovery(onDiscovered) {
|
|
24
64
|
const manager = new ESPDiscoveryManager.ESPDiscoveryManager();
|
|
25
|
-
manager.startDiscovery((info) =>
|
|
65
|
+
manager.startDiscovery((info) => {
|
|
66
|
+
const data = toDiscoveredNodeData(info);
|
|
67
|
+
if (data)
|
|
68
|
+
onDiscovered(data);
|
|
69
|
+
});
|
|
26
70
|
return { stop: () => manager.stopDiscovery() };
|
|
27
71
|
}
|
|
28
72
|
/** Forwards process-wide node param updates to `onUpdate`. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eventSubscriptionUtils.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"eventSubscriptionUtils.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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/esm/ESPRMNeoBase.js
CHANGED
|
@@ -183,7 +183,7 @@ class ESPRMNeoBase {
|
|
|
183
183
|
}
|
|
184
184
|
/**
|
|
185
185
|
* Sets the local control adapter used to talk to nodes over the LAN via
|
|
186
|
-
* the `
|
|
186
|
+
* the `rmaker_local_ctrl` protocol.
|
|
187
187
|
*
|
|
188
188
|
* @param adapter - Adapter implementing {@link ESPLocalControlAdapterInterface}.
|
|
189
189
|
* @throws {Error} If the SDK is not initialized or the adapter is invalid.
|
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
|
@@ -15,7 +15,7 @@ export { ESPDevice } from './ESPDevice.js';
|
|
|
15
15
|
export { ESPDiscoveryProtocol, ESPRMNeoEventType } from './types/discovery.js';
|
|
16
16
|
export { ESPClaimStatus, ESPConnectStatus, ESPProvResponseStatus, ESPProvisionStatus, ESPSecurity, ESPTransport } from './types/provision.js';
|
|
17
17
|
export { resolveNodeId } from './types/subscription.js';
|
|
18
|
-
export { DEFAULT_TRANSPORT_ORDER, ESPTransportMode } from './types/transport.js';
|
|
18
|
+
export { DEFAULT_LOCAL_CONTROL_PROTOCOL, DEFAULT_TRANSPORT_ORDER, ESPLocalControlProtocol, ESPTransportMode } from './types/transport.js';
|
|
19
19
|
import './methods/ESPRMNeoAuth/ChangePassword.js';
|
|
20
20
|
import './methods/ESPRMNeoAuth/ConfirmSignUp.js';
|
|
21
21
|
import './methods/ESPRMNeoAuth/ForgotPassword.js';
|
|
@@ -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, RMAKER_LOCAL_CTRL_FRAGMENT_SIZE, RMAKER_LOCAL_CTRL_VERSION_KEY, RMakerLocalCtrlCapability, RMakerLocalCtrlEndpoint, RMakerLocalCtrlSetParamsStatus, RMakerLocalCtrlTxtKey, 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":";;;;;;;;;;;;;;;;;;;;;;"}
|