@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
|
@@ -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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
|
3
|
+
*
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Codec for the `rmaker_local_ctrl` endpoint protocol, mirroring the firmware's
|
|
8
|
+
* `local_ctrl.proto` schema.
|
|
9
|
+
*
|
|
10
|
+
* Hand-rolled like {@link ClaimingProtoHelper} rather than generated: the
|
|
11
|
+
* schema is small, and generated `google-protobuf` modules cannot be pulled
|
|
12
|
+
* into a downstream Metro/RN bundle (see the note in `utils/export.ts`).
|
|
13
|
+
*
|
|
14
|
+
* Field numbers are the wire contract with deployed firmware — treat them as
|
|
15
|
+
* frozen:
|
|
16
|
+
* - `RMakerLocalCtrlPayload`: 1 = msg (varint), 10 = cmdGetData, 11 = respGetData
|
|
17
|
+
* - `CmdGetData`: 1 = DataType (varint), 2 = Offset (varint),
|
|
18
|
+
* 3 = Timestamp (varint), 4 = HasTimestamp (varint)
|
|
19
|
+
* - `RespGetData`: 1 = Status (varint), 2 = Buf
|
|
20
|
+
* - `PayloadBuf`: 1 = Offset (varint), 2 = Payload (bytes), 3 = TotalLen (varint)
|
|
21
|
+
*
|
|
22
|
+
* `Timestamp` / `HasTimestamp` are reserved for a future signed-response
|
|
23
|
+
* extension and are ignored by current firmware, so the encoder omits them.
|
|
24
|
+
*
|
|
25
|
+
* Only `get_params` / `get_config` use this schema; `set_params` carries raw
|
|
26
|
+
* JSON on the wire.
|
|
27
|
+
*/
|
|
28
|
+
/**
|
|
29
|
+
* Status returned by the device for a data read.
|
|
30
|
+
*/
|
|
31
|
+
var RMakerLocalCtrlStatus;
|
|
32
|
+
(function (RMakerLocalCtrlStatus) {
|
|
33
|
+
RMakerLocalCtrlStatus[RMakerLocalCtrlStatus["Success"] = 0] = "Success";
|
|
34
|
+
RMakerLocalCtrlStatus[RMakerLocalCtrlStatus["Fail"] = 1] = "Fail";
|
|
35
|
+
RMakerLocalCtrlStatus[RMakerLocalCtrlStatus["InvalidParam"] = 2] = "InvalidParam";
|
|
36
|
+
RMakerLocalCtrlStatus[RMakerLocalCtrlStatus["NoMemory"] = 3] = "NoMemory";
|
|
37
|
+
})(RMakerLocalCtrlStatus || (RMakerLocalCtrlStatus = {}));
|
|
38
|
+
/**
|
|
39
|
+
* Selects which document a read targets.
|
|
40
|
+
*/
|
|
41
|
+
var RMakerLocalCtrlDataType;
|
|
42
|
+
(function (RMakerLocalCtrlDataType) {
|
|
43
|
+
/** The node's params JSON, as served by `get_params`. */
|
|
44
|
+
RMakerLocalCtrlDataType[RMakerLocalCtrlDataType["TypeParams"] = 0] = "TypeParams";
|
|
45
|
+
/** The node's config JSON, as served by `get_config`. */
|
|
46
|
+
RMakerLocalCtrlDataType[RMakerLocalCtrlDataType["TypeConfig"] = 1] = "TypeConfig";
|
|
47
|
+
})(RMakerLocalCtrlDataType || (RMakerLocalCtrlDataType = {}));
|
|
48
|
+
/**
|
|
49
|
+
* Message type discriminator carried on `RMakerLocalCtrlPayload.msg`.
|
|
50
|
+
*/
|
|
51
|
+
var RMakerLocalCtrlMsgType;
|
|
52
|
+
(function (RMakerLocalCtrlMsgType) {
|
|
53
|
+
RMakerLocalCtrlMsgType[RMakerLocalCtrlMsgType["TypeCmdGetData"] = 0] = "TypeCmdGetData";
|
|
54
|
+
RMakerLocalCtrlMsgType[RMakerLocalCtrlMsgType["TypeRespGetData"] = 1] = "TypeRespGetData";
|
|
55
|
+
})(RMakerLocalCtrlMsgType || (RMakerLocalCtrlMsgType = {}));
|
|
56
|
+
/** Tag bytes written by the request encoder: `(fieldNumber << 3) | wireType`. */
|
|
57
|
+
const TAG_FIELD_1_VARINT = 0x08;
|
|
58
|
+
const TAG_FIELD_2_VARINT = 0x10;
|
|
59
|
+
const TAG_FIELD_10_BYTES = 0x52;
|
|
60
|
+
const WIRE_TYPE_VARINT = 0;
|
|
61
|
+
const WIRE_TYPE_BYTES = 2;
|
|
62
|
+
/**
|
|
63
|
+
* Encoder/decoder for `rmaker_local_ctrl` frames.
|
|
64
|
+
*/
|
|
65
|
+
class RMakerLocalCtrlProtoHelper {
|
|
66
|
+
/**
|
|
67
|
+
* Builds a `CmdGetData` request for one fragment.
|
|
68
|
+
*
|
|
69
|
+
* An `offset` of 0 makes the device (re)generate and cache the document;
|
|
70
|
+
* subsequent offsets are served from that cache.
|
|
71
|
+
*
|
|
72
|
+
* @param dataType - Document to read.
|
|
73
|
+
* @param offset - Byte offset to read from.
|
|
74
|
+
* @returns The serialized request.
|
|
75
|
+
*/
|
|
76
|
+
static createGetDataRequest(dataType, offset) {
|
|
77
|
+
const cmdGetData = this.concat([
|
|
78
|
+
// Both fields are written explicitly, including their proto3 zero values,
|
|
79
|
+
// matching how the reference clients frame this command.
|
|
80
|
+
new Uint8Array([TAG_FIELD_1_VARINT]),
|
|
81
|
+
this.encodeVarint(dataType),
|
|
82
|
+
new Uint8Array([TAG_FIELD_2_VARINT]),
|
|
83
|
+
this.encodeVarint(offset),
|
|
84
|
+
]);
|
|
85
|
+
return this.concat([
|
|
86
|
+
new Uint8Array([TAG_FIELD_1_VARINT]),
|
|
87
|
+
this.encodeVarint(RMakerLocalCtrlMsgType.TypeCmdGetData),
|
|
88
|
+
new Uint8Array([TAG_FIELD_10_BYTES]),
|
|
89
|
+
this.encodeVarint(cmdGetData.length),
|
|
90
|
+
cmdGetData,
|
|
91
|
+
]);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Parses a `RespGetData` frame from the device.
|
|
95
|
+
*
|
|
96
|
+
* @param data - Raw response bytes.
|
|
97
|
+
* @returns The parsed payload. Absent fields keep their proto3 defaults.
|
|
98
|
+
*/
|
|
99
|
+
static parseGetDataResponse(data) {
|
|
100
|
+
const result = {
|
|
101
|
+
msg: RMakerLocalCtrlMsgType.TypeCmdGetData,
|
|
102
|
+
};
|
|
103
|
+
let index = 0;
|
|
104
|
+
while (index < data.length) {
|
|
105
|
+
const tag = data[index++];
|
|
106
|
+
const fieldNumber = tag >> 3;
|
|
107
|
+
const wireType = tag & 0x07;
|
|
108
|
+
if (fieldNumber === 1 && wireType === WIRE_TYPE_VARINT) {
|
|
109
|
+
const { value, newIndex } = this.readVarint(data, index);
|
|
110
|
+
result.msg = value;
|
|
111
|
+
index = newIndex;
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
if (fieldNumber === 11 && wireType === WIRE_TYPE_BYTES) {
|
|
115
|
+
const { value: length, newIndex } = this.readVarint(data, index);
|
|
116
|
+
result.respGetData = this.parseRespGetData(data.slice(newIndex, newIndex + length));
|
|
117
|
+
index = newIndex + length;
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
index = this.skipField(data, index, wireType);
|
|
121
|
+
}
|
|
122
|
+
return result;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Whether the device reported a successful read.
|
|
126
|
+
*
|
|
127
|
+
* @param response - Parsed response.
|
|
128
|
+
*/
|
|
129
|
+
static isSuccess(response) {
|
|
130
|
+
return response.respGetData?.status === RMakerLocalCtrlStatus.Success;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Returns the device's status as its enum name, for diagnostics.
|
|
134
|
+
*
|
|
135
|
+
* @param response - Parsed response.
|
|
136
|
+
* @returns The status name, or `"Unknown"` when absent.
|
|
137
|
+
*/
|
|
138
|
+
static getStatus(response) {
|
|
139
|
+
const status = response.respGetData?.status;
|
|
140
|
+
return status === undefined
|
|
141
|
+
? "Unknown"
|
|
142
|
+
: (RMakerLocalCtrlStatus[status] ?? `Unknown(${status})`);
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Offset the device answered with, which must match the requested offset.
|
|
146
|
+
*
|
|
147
|
+
* @param response - Parsed response.
|
|
148
|
+
*/
|
|
149
|
+
static getOffset(response) {
|
|
150
|
+
return response.respGetData?.buf?.offset ?? 0;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Full document length reported by the device.
|
|
154
|
+
*
|
|
155
|
+
* @param response - Parsed response.
|
|
156
|
+
*/
|
|
157
|
+
static getTotalLen(response) {
|
|
158
|
+
return response.respGetData?.buf?.totalLen ?? 0;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Fragment bytes carried by the response.
|
|
162
|
+
*
|
|
163
|
+
* @param response - Parsed response.
|
|
164
|
+
*/
|
|
165
|
+
static getPayload(response) {
|
|
166
|
+
return response.respGetData?.buf?.payload ?? new Uint8Array(0);
|
|
167
|
+
}
|
|
168
|
+
// Private helper methods
|
|
169
|
+
static concat(parts) {
|
|
170
|
+
const totalLength = parts.reduce((sum, part) => sum + part.length, 0);
|
|
171
|
+
const result = new Uint8Array(totalLength);
|
|
172
|
+
let pos = 0;
|
|
173
|
+
for (const part of parts) {
|
|
174
|
+
result.set(part, pos);
|
|
175
|
+
pos += part.length;
|
|
176
|
+
}
|
|
177
|
+
return result;
|
|
178
|
+
}
|
|
179
|
+
static encodeVarint(value) {
|
|
180
|
+
const bytes = [];
|
|
181
|
+
let remaining = value;
|
|
182
|
+
while (remaining > 127) {
|
|
183
|
+
bytes.push((remaining & 0x7f) | 0x80);
|
|
184
|
+
remaining >>>= 7;
|
|
185
|
+
}
|
|
186
|
+
bytes.push(remaining & 0x7f);
|
|
187
|
+
return new Uint8Array(bytes);
|
|
188
|
+
}
|
|
189
|
+
static readVarint(data, index) {
|
|
190
|
+
let value = 0;
|
|
191
|
+
let shift = 0;
|
|
192
|
+
let byte;
|
|
193
|
+
do {
|
|
194
|
+
byte = data[index++];
|
|
195
|
+
value |= (byte & 0x7f) << shift;
|
|
196
|
+
shift += 7;
|
|
197
|
+
} while (byte & 0x80);
|
|
198
|
+
return { value, newIndex: index };
|
|
199
|
+
}
|
|
200
|
+
/** Advances past a field this codec does not read. */
|
|
201
|
+
static skipField(data, index, wireType) {
|
|
202
|
+
if (wireType === WIRE_TYPE_VARINT) {
|
|
203
|
+
return this.readVarint(data, index).newIndex;
|
|
204
|
+
}
|
|
205
|
+
if (wireType === WIRE_TYPE_BYTES) {
|
|
206
|
+
const { value: length, newIndex } = this.readVarint(data, index);
|
|
207
|
+
return newIndex + length;
|
|
208
|
+
}
|
|
209
|
+
return index + 1;
|
|
210
|
+
}
|
|
211
|
+
static parseRespGetData(data) {
|
|
212
|
+
// In proto3 an absent status defaults to 0, i.e. Success.
|
|
213
|
+
const result = { status: RMakerLocalCtrlStatus.Success };
|
|
214
|
+
let index = 0;
|
|
215
|
+
while (index < data.length) {
|
|
216
|
+
const tag = data[index++];
|
|
217
|
+
const fieldNumber = tag >> 3;
|
|
218
|
+
const wireType = tag & 0x07;
|
|
219
|
+
if (fieldNumber === 1 && wireType === WIRE_TYPE_VARINT) {
|
|
220
|
+
const { value, newIndex } = this.readVarint(data, index);
|
|
221
|
+
result.status = value;
|
|
222
|
+
index = newIndex;
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
if (fieldNumber === 2 && wireType === WIRE_TYPE_BYTES) {
|
|
226
|
+
const { value: length, newIndex } = this.readVarint(data, index);
|
|
227
|
+
result.buf = this.parsePayloadBuf(data.slice(newIndex, newIndex + length));
|
|
228
|
+
index = newIndex + length;
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
index = this.skipField(data, index, wireType);
|
|
232
|
+
}
|
|
233
|
+
return result;
|
|
234
|
+
}
|
|
235
|
+
static parsePayloadBuf(data) {
|
|
236
|
+
const result = {
|
|
237
|
+
offset: 0,
|
|
238
|
+
payload: new Uint8Array(0),
|
|
239
|
+
totalLen: 0,
|
|
240
|
+
};
|
|
241
|
+
let index = 0;
|
|
242
|
+
while (index < data.length) {
|
|
243
|
+
const tag = data[index++];
|
|
244
|
+
const fieldNumber = tag >> 3;
|
|
245
|
+
const wireType = tag & 0x07;
|
|
246
|
+
if (fieldNumber === 1 && wireType === WIRE_TYPE_VARINT) {
|
|
247
|
+
const { value, newIndex } = this.readVarint(data, index);
|
|
248
|
+
result.offset = value;
|
|
249
|
+
index = newIndex;
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
252
|
+
if (fieldNumber === 2 && wireType === WIRE_TYPE_BYTES) {
|
|
253
|
+
const { value: length, newIndex } = this.readVarint(data, index);
|
|
254
|
+
result.payload = data.slice(newIndex, newIndex + length);
|
|
255
|
+
index = newIndex + length;
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
if (fieldNumber === 3 && wireType === WIRE_TYPE_VARINT) {
|
|
259
|
+
const { value, newIndex } = this.readVarint(data, index);
|
|
260
|
+
result.totalLen = value;
|
|
261
|
+
index = newIndex;
|
|
262
|
+
continue;
|
|
263
|
+
}
|
|
264
|
+
index = this.skipField(data, index, wireType);
|
|
265
|
+
}
|
|
266
|
+
return result;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
export { RMakerLocalCtrlDataType, RMakerLocalCtrlMsgType, RMakerLocalCtrlProtoHelper, RMakerLocalCtrlStatus };
|
|
271
|
+
//# sourceMappingURL=rmaker_local_ctrl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rmaker_local_ctrl.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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -12,9 +12,10 @@ import { ServiceType } from '../../../utils/constants.js';
|
|
|
12
12
|
* adapter (see {@link ESPRMNeoBase.setLocalDiscoveryAdapter}).
|
|
13
13
|
*
|
|
14
14
|
* - With no discovery config, the default local protocol is used
|
|
15
|
-
* (mDNS service `
|
|
16
|
-
*
|
|
17
|
-
*
|
|
15
|
+
* (mDNS service `_esp_rmaker_ctrl._tcp.` in the `local` domain — the
|
|
16
|
+
* service advertised by RainMaker Neo firmware).
|
|
17
|
+
* - A custom {@link DiscoveryParamsInterface} can be supplied to browse any
|
|
18
|
+
* other service type.
|
|
18
19
|
*/
|
|
19
20
|
class ESPDiscoveryManager {
|
|
20
21
|
/** Discovery parameters (service type / domain) passed to the adapter. */
|
|
@@ -29,7 +30,7 @@ class ESPDiscoveryManager {
|
|
|
29
30
|
throw new Error("ESPLocalDiscoveryAdapter not set");
|
|
30
31
|
}
|
|
31
32
|
this.params = discoveryConfig || {
|
|
32
|
-
serviceType: ServiceType.
|
|
33
|
+
serviceType: ServiceType.ESP_RMAKER_LOCAL_CTRL_TCP,
|
|
33
34
|
domain: ESPDiscoveryProtocol.local,
|
|
34
35
|
};
|
|
35
36
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ESPDiscoveryManager.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ESPDiscoveryManager.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|