@ray-js/robot-data-stream 0.0.17-beta.9 → 0.1.0-beta.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.
Files changed (53) hide show
  1. package/README.md +23 -1
  2. package/lib/api/index.d.ts +1 -0
  3. package/lib/api/p2pApi.d.ts +30 -7
  4. package/lib/api/p2pApi.js +59 -23
  5. package/lib/api/sweeperP2p.d.ts +18 -1
  6. package/lib/api/sweeperP2p.js +177 -25
  7. package/lib/index.d.ts +15 -9
  8. package/lib/index.js +60 -3
  9. package/lib/mqtt/createCommonOptions.d.ts +2 -20
  10. package/lib/mqtt/createCommonOptions.js +17 -5
  11. package/lib/mqtt/defineRobotCommand.d.ts +52 -0
  12. package/lib/mqtt/defineRobotCommand.js +71 -0
  13. package/lib/mqtt/hooks/useStructuredMessage.d.ts +5 -1
  14. package/lib/mqtt/hooks/useStructuredMessage.js +22 -10
  15. package/lib/mqtt/index.d.ts +7 -1
  16. package/lib/mqtt/index.js +11 -1
  17. package/lib/mqtt/promise.d.ts +21 -6
  18. package/lib/mqtt/promise.js +47 -12
  19. package/lib/mqtt/type/protocols/carpetProtocol.d.ts +2 -0
  20. package/lib/mqtt/type/protocols/index.d.ts +2 -0
  21. package/lib/mqtt/type/protocols/index.js +3 -1
  22. package/lib/mqtt/type/protocols/thresholdProtocol.d.ts +22 -0
  23. package/lib/mqtt/type/protocols/thresholdProtocol.js +1 -0
  24. package/lib/mqtt/type/requestType.d.ts +4 -0
  25. package/lib/mqtt/type/requestType.js +7 -0
  26. package/lib/mqtt/useCarpet.js +12 -4
  27. package/lib/mqtt/useCarpetClean.js +6 -2
  28. package/lib/mqtt/useCruise.js +3 -1
  29. package/lib/mqtt/useCustomCommand.d.ts +39 -0
  30. package/lib/mqtt/useCustomCommand.js +45 -0
  31. package/lib/mqtt/useDeviceModel.js +3 -1
  32. package/lib/mqtt/useFurnitureModel.js +3 -1
  33. package/lib/mqtt/useHistoryMap.js +9 -3
  34. package/lib/mqtt/usePartDivision.js +3 -1
  35. package/lib/mqtt/usePartMerge.js +3 -1
  36. package/lib/mqtt/usePassword.js +6 -2
  37. package/lib/mqtt/usePurifierSchedule.js +3 -1
  38. package/lib/mqtt/useQuiteHours.js +3 -1
  39. package/lib/mqtt/useResetMap.js +3 -1
  40. package/lib/mqtt/useRoomProperty.js +3 -1
  41. package/lib/mqtt/useSchedule.js +3 -1
  42. package/lib/mqtt/useSelectRoomClean.js +3 -1
  43. package/lib/mqtt/useSpotClean.js +3 -1
  44. package/lib/mqtt/useSpotPolygons.js +3 -1
  45. package/lib/mqtt/useThreshold.d.ts +10 -0
  46. package/lib/mqtt/useThreshold.js +90 -0
  47. package/lib/mqtt/useVirtualArea.js +3 -1
  48. package/lib/mqtt/useVirtualWall.js +3 -1
  49. package/lib/mqtt/useVoice.js +3 -1
  50. package/lib/mqtt/useWifiMap.js +3 -1
  51. package/lib/mqtt/useZoneClean.js +3 -1
  52. package/lib/utils/index.d.ts +7 -7
  53. package/package.json +5 -1
@@ -78,7 +78,9 @@ export const useCarpet = () => {
78
78
  const sendData = pickBy(processedData, value => value !== undefined);
79
79
  sendStructuredMessage(CarpetEnum.update, {
80
80
  carpetInfo: sendData
81
- }, resolve, error => reject(handleMqttError(error, 'Failed to update carpet')), CarpetEnum.update);
81
+ }, resolve, error => reject(handleMqttError(error, 'Failed to update carpet')), {
82
+ responseType: CarpetEnum.update
83
+ });
82
84
  } catch (error) {
83
85
  reject(handleMqttError(error, 'Failed to update carpet'));
84
86
  }
@@ -91,7 +93,9 @@ export const useCarpet = () => {
91
93
  carpetInfo: {
92
94
  ids: data.ids
93
95
  }
94
- }, resolve, error => reject(handleMqttError(error, 'Failed to delete carpet')), CarpetEnum.delete);
96
+ }, resolve, error => reject(handleMqttError(error, 'Failed to delete carpet')), {
97
+ responseType: CarpetEnum.delete
98
+ });
95
99
  } catch (error) {
96
100
  reject(handleMqttError(error, 'Failed to delete carpet'));
97
101
  }
@@ -101,7 +105,9 @@ export const useCarpet = () => {
101
105
  let data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
102
106
  return new Promise((resolve, reject) => {
103
107
  try {
104
- sendStructuredMessage(CarpetEnum.query, data, resolve, error => reject(handleMqttError(error, 'Failed to query carpet')), CarpetEnum.query);
108
+ sendStructuredMessage(CarpetEnum.query, data, resolve, error => reject(handleMqttError(error, 'Failed to query carpet')), {
109
+ responseType: CarpetEnum.query
110
+ });
105
111
  } catch (error) {
106
112
  reject(handleMqttError(error, 'Failed to query carpet'));
107
113
  }
@@ -121,7 +127,9 @@ export const useCarpet = () => {
121
127
  ids: carpetInfo.ids,
122
128
  type: carpetInfo.type
123
129
  };
124
- sendStructuredMessage(CarpetEnum.set, sendData, resolve, error => reject(handleMqttError(error, 'Failed to set carpet')), CarpetEnum.query);
130
+ sendStructuredMessage(CarpetEnum.set, sendData, resolve, error => reject(handleMqttError(error, 'Failed to set carpet')), {
131
+ responseType: CarpetEnum.query
132
+ });
125
133
  } catch (error) {
126
134
  reject(handleMqttError(error, 'Failed to set carpet'));
127
135
  }
@@ -27,7 +27,9 @@ export const useCarpetClean = () => {
27
27
  requestCarpetClean: () => {
28
28
  return new Promise((resolve, reject) => {
29
29
  try {
30
- sendStructuredMessage(CarpetCleanEnum.query, {}, resolve, error => reject(handleMqttError(error, 'Failed to request carpet clean')), CarpetCleanEnum.query);
30
+ sendStructuredMessage(CarpetCleanEnum.query, {}, resolve, error => reject(handleMqttError(error, 'Failed to request carpet clean')), {
31
+ responseType: CarpetCleanEnum.query
32
+ });
31
33
  } catch (error) {
32
34
  reject(handleMqttError(error, 'Failed to request carpet clean'));
33
35
  }
@@ -38,7 +40,9 @@ export const useCarpetClean = () => {
38
40
  try {
39
41
  sendStructuredMessage(CarpetCleanEnum.set, {
40
42
  ids: data
41
- }, resolve, error => reject(handleMqttError(error, 'Failed to set carpet clean')), CarpetCleanEnum.set);
43
+ }, resolve, error => reject(handleMqttError(error, 'Failed to set carpet clean')), {
44
+ responseType: CarpetCleanEnum.set
45
+ });
42
46
  } catch (error) {
43
47
  reject(handleMqttError(error, 'Failed to set carpet clean'));
44
48
  }
@@ -56,7 +56,9 @@ export const useCruise = () => {
56
56
  reject(new Error('cruiseType is required when cmd is "start"'));
57
57
  return;
58
58
  }
59
- sendStructuredMessage(CruiseEnum.set, createCruisePayload(message), resolve, error => reject(handleMqttError(error, 'Failed to set cruise')), CruiseEnum.query // 响应类型是 query,不是 set
59
+ sendStructuredMessage(CruiseEnum.set, createCruisePayload(message), resolve, error => reject(handleMqttError(error, 'Failed to set cruise')), {
60
+ responseType: CruiseEnum.query
61
+ } // 响应类型是 query,不是 set
60
62
  );
61
63
  } catch (error) {
62
64
  reject(handleMqttError(error, 'Failed to set cruise'));
@@ -0,0 +1,39 @@
1
+ import { BaseResponse } from './type/protocols/base';
2
+ /**
3
+ * 自定义指令选项
4
+ */
5
+ export interface CustomCommandOptions {
6
+ /**
7
+ * 响应匹配的事件名(reqType)。
8
+ * 缺省与下发 reqType 同名;set 类指令的回复走 qry 事件名、
9
+ * 或回复 reqType 与下发不同名(如 aiObjectIgnoreSet → aiObjectIgnoreRst)时必填。
10
+ */
11
+ responseType?: string;
12
+ /** 超时时间(毫秒),默认 10000 */
13
+ timeout?: number;
14
+ /** 协议版本号,默认 '1.0.0' */
15
+ version?: string;
16
+ }
17
+ /**
18
+ * 自定义指令发送函数类型
19
+ */
20
+ export type TSendCustomCommand = <TRes extends BaseResponse = BaseResponse>(reqType: string, data?: Record<string, any>, options?: CustomCommandOptions) => Promise<TRes>;
21
+ /**
22
+ * 自定义指令 Hook:在 MqttProvider 内任意组件使用,获得 sendCustomCommand。
23
+ *
24
+ * 与内置 hook 同一契约:返回 Promise 命令函数,loading / 重试 / toast 由业务侧自理。
25
+ * 走 MQTT + LAN JSON socket 双通道(复用 preferredChannel 策略);
26
+ * DP command_trans 二进制路线不支持(useMqtt=false 时直接 reject)。
27
+ * 响应按 reqType + taskId 双匹配,同 reqType 并发下发不会互相串包。
28
+ *
29
+ * @example
30
+ * ```typescript
31
+ * const { sendCustomCommand } = useCustomCommand();
32
+ *
33
+ * // 下发查询并等待回复
34
+ * const res = await sendCustomCommand<PeakValleyResponse>('peakValleyChargeQry');
35
+ * ```
36
+ */
37
+ export declare const useCustomCommand: () => {
38
+ sendCustomCommand: TSendCustomCommand;
39
+ };
@@ -0,0 +1,45 @@
1
+ // 自定义指令:不经过内置 hook 的任意 reqType 下发出口
2
+ import { useCallback } from 'react';
3
+ import { handleMqttError, useStructuredMessage } from './hooks/useStructuredMessage';
4
+
5
+ /**
6
+ * 自定义指令选项
7
+ */
8
+
9
+ /**
10
+ * 自定义指令发送函数类型
11
+ */
12
+
13
+ /**
14
+ * 自定义指令 Hook:在 MqttProvider 内任意组件使用,获得 sendCustomCommand。
15
+ *
16
+ * 与内置 hook 同一契约:返回 Promise 命令函数,loading / 重试 / toast 由业务侧自理。
17
+ * 走 MQTT + LAN JSON socket 双通道(复用 preferredChannel 策略);
18
+ * DP command_trans 二进制路线不支持(useMqtt=false 时直接 reject)。
19
+ * 响应按 reqType + taskId 双匹配,同 reqType 并发下发不会互相串包。
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * const { sendCustomCommand } = useCustomCommand();
24
+ *
25
+ * // 下发查询并等待回复
26
+ * const res = await sendCustomCommand<PeakValleyResponse>('peakValleyChargeQry');
27
+ * ```
28
+ */
29
+ export const useCustomCommand = () => {
30
+ const {
31
+ sendStructuredMessage
32
+ } = useStructuredMessage();
33
+ const sendCustomCommand = useCallback(function (reqType) {
34
+ let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
35
+ let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
36
+ return new Promise((resolve, reject) => {
37
+ sendStructuredMessage(reqType, data,
38
+ // Promise 的 resolve 入参是 TRes 的超集(含 PromiseLike),收窄传给发送层
39
+ resolve, error => reject(handleMqttError(error, `Failed to send custom command ${reqType}`)), options);
40
+ });
41
+ }, [sendStructuredMessage]);
42
+ return {
43
+ sendCustomCommand
44
+ };
45
+ };
@@ -36,7 +36,9 @@ export const useDeviceModel = () => {
36
36
  try {
37
37
  sendStructuredMessage(DeviceModelEnum.set, {
38
38
  modelInfos: data
39
- }, resolve, error => reject(handleMqttError(error, 'Failed to set device model')), DeviceModelEnum.query);
39
+ }, resolve, error => reject(handleMqttError(error, 'Failed to set device model')), {
40
+ responseType: DeviceModelEnum.query
41
+ });
40
42
  } catch (error) {
41
43
  reject(handleMqttError(error, 'Failed to set device model'));
42
44
  }
@@ -36,7 +36,9 @@ export const useFurnitureModel = () => {
36
36
  try {
37
37
  sendStructuredMessage(FurnitureModelEnum.set, {
38
38
  modelInfos: data
39
- }, resolve, error => reject(handleMqttError(error, 'Failed to set furniture model')), FurnitureModelEnum.query);
39
+ }, resolve, error => reject(handleMqttError(error, 'Failed to set furniture model')), {
40
+ responseType: FurnitureModelEnum.query
41
+ });
40
42
  } catch (error) {
41
43
  reject(handleMqttError(error, 'Failed to set furniture model'));
42
44
  }
@@ -48,7 +48,9 @@ export const useHistoryMap = () => {
48
48
  if (useMqtt) {
49
49
  sendStructuredMessage(DeleteMapEnum.set, {
50
50
  mapId
51
- }, resolve, error => reject(handleMqttError(error, 'Failed to delete history map')), DeleteMapEnum.rst // 响应类型是 rst,不是 set
51
+ }, resolve, error => reject(handleMqttError(error, 'Failed to delete history map')), {
52
+ responseType: DeleteMapEnum.rst
53
+ } // 响应类型是 rst,不是 set
52
54
  );
53
55
  return;
54
56
  }
@@ -81,7 +83,9 @@ export const useHistoryMap = () => {
81
83
  urlLen: url.length
82
84
  };
83
85
  if (useMqtt) {
84
- sendStructuredMessage(UseMapEnum.set, mapData, resolve, error => reject(handleMqttError(error, 'Failed to change current map')), UseMapEnum.query // 响应类型是 query,不是 set
86
+ sendStructuredMessage(UseMapEnum.set, mapData, resolve, error => reject(handleMqttError(error, 'Failed to change current map')), {
87
+ responseType: UseMapEnum.query
88
+ } // 响应类型是 query,不是 set
85
89
  );
86
90
  return;
87
91
  }
@@ -113,7 +117,9 @@ export const useHistoryMap = () => {
113
117
  return new Promise((resolve, reject) => {
114
118
  try {
115
119
  if (useMqtt) {
116
- sendStructuredMessage(SaveCurrentMapEnum.set, data, resolve, error => reject(handleMqttError(error, 'Failed to save current map')), SaveCurrentMapEnum.query // 响应类型是 query,不是 set
120
+ sendStructuredMessage(SaveCurrentMapEnum.set, data, resolve, error => reject(handleMqttError(error, 'Failed to save current map')), {
121
+ responseType: SaveCurrentMapEnum.query
122
+ } // 响应类型是 query,不是 set
117
123
  );
118
124
  return;
119
125
  }
@@ -36,7 +36,9 @@ export const usePartDivision = () => {
36
36
  sendStructuredMessage(PartDivisionEnum.set, {
37
37
  lines: [pointStr],
38
38
  ids: [roomId]
39
- }, resolve, error => reject(handleMqttError(error, 'Failed to set part division')), PartDivisionEnum.query);
39
+ }, resolve, error => reject(handleMqttError(error, 'Failed to set part division')), {
40
+ responseType: PartDivisionEnum.query
41
+ });
40
42
  return;
41
43
  }
42
44
  const roomIdNumber = typeof roomId === 'string' ? Number(roomId) : roomId;
@@ -31,7 +31,9 @@ export const usePartMerge = () => {
31
31
  if (useMqtt) {
32
32
  sendStructuredMessage(PartMergeEnum.set, {
33
33
  ids
34
- }, resolve, error => reject(handleMqttError(error, 'Failed to set part merge')), PartMergeEnum.query // 响应类型是 query,不是 set
34
+ }, resolve, error => reject(handleMqttError(error, 'Failed to set part merge')), {
35
+ responseType: PartMergeEnum.query
36
+ } // 响应类型是 query,不是 set
35
37
  );
36
38
  return;
37
39
  }
@@ -64,7 +64,9 @@ export const usePassword = () => {
64
64
  oldPassword: params.oldPassword ? md5(params.oldPassword).toString() : undefined,
65
65
  taskId: (_params$taskId = params.taskId) !== null && _params$taskId !== void 0 ? _params$taskId : String(Date.now())
66
66
  };
67
- sendStructuredMessage(PasswordEnum.set, passwordData, resolve, error => reject(handleMqttError(error, 'Failed to set password')), PasswordEnum.rst // 响应类型是 rst,不是 set
67
+ sendStructuredMessage(PasswordEnum.set, passwordData, resolve, error => reject(handleMqttError(error, 'Failed to set password')), {
68
+ responseType: PasswordEnum.rst
69
+ } // 响应类型是 rst,不是 set
68
70
  );
69
71
  } catch (error) {
70
72
  reject(handleMqttError(error, 'Failed to set password'));
@@ -86,7 +88,9 @@ export const usePassword = () => {
86
88
  password: md5(params.password).toString(),
87
89
  taskId: (_params$taskId2 = params.taskId) !== null && _params$taskId2 !== void 0 ? _params$taskId2 : String(Date.now())
88
90
  };
89
- sendStructuredMessage(PasswordEnum.check, passwordData, resolve, error => reject(handleMqttError(error, 'Failed to check password')), PasswordEnum.checkRst // 响应类型是 checkRst,不是 check
91
+ sendStructuredMessage(PasswordEnum.check, passwordData, resolve, error => reject(handleMqttError(error, 'Failed to check password')), {
92
+ responseType: PasswordEnum.checkRst
93
+ } // 响应类型是 checkRst,不是 check
90
94
  );
91
95
  } catch (error) {
92
96
  reject(handleMqttError(error, 'Failed to check password'));
@@ -55,7 +55,9 @@ export const usePurifierSchedule = () => {
55
55
  }
56
56
  sendStructuredMessage(PurifierScheduleEnum.set, _objectSpread(_objectSpread({}, message), {}, {
57
57
  num: (_message$num = message.num) !== null && _message$num !== void 0 ? _message$num : message.list.length
58
- }), resolve, error => reject(handleMqttError(error, 'Failed to set purifier schedule')), PurifierScheduleEnum.query // 响应类型是 query,不是 set
58
+ }), resolve, error => reject(handleMqttError(error, 'Failed to set purifier schedule')), {
59
+ responseType: PurifierScheduleEnum.query
60
+ } // 响应类型是 query,不是 set
59
61
  );
60
62
  } catch (error) {
61
63
  reject(handleMqttError(error, 'Failed to set purifier schedule'));
@@ -52,7 +52,9 @@ export const useQuiteHours = () => {
52
52
  time: [`${h0},${m0}`, `${h1},${m1}`],
53
53
  active,
54
54
  day
55
- }, resolve, error => reject(handleMqttError(error, 'Failed to set quiet hours')), QuietHoursEnum.query // 响应类型是 query,不是 set
55
+ }, resolve, error => reject(handleMqttError(error, 'Failed to set quiet hours')), {
56
+ responseType: QuietHoursEnum.query
57
+ } // 响应类型是 query,不是 set
56
58
  );
57
59
  return;
58
60
  }
@@ -28,7 +28,9 @@ export const useResetMap = () => {
28
28
  return new Promise((resolve, reject) => {
29
29
  try {
30
30
  if (useMqtt) {
31
- sendStructuredMessage(ResetCurrMapEnum.set, {}, resolve, error => reject(handleMqttError(error, 'Failed to reset map')), ResetCurrMapEnum.query // 响应类型是 query,不是 set
31
+ sendStructuredMessage(ResetCurrMapEnum.set, {}, resolve, error => reject(handleMqttError(error, 'Failed to reset map')), {
32
+ responseType: ResetCurrMapEnum.query
33
+ } // 响应类型是 query,不是 set
32
34
  );
33
35
  return;
34
36
  }
@@ -73,7 +73,9 @@ export const useRoomProperty = () => {
73
73
  }), data.polygons && {
74
74
  polygons: data.polygons
75
75
  }), pickWaterFields(len, data.cisterns, data.waterValues));
76
- sendStructuredMessage(RoomPropertyEnum.set, sendData, resolve, error => reject(handleMqttError(error, 'Failed to set room property')), RoomPropertyEnum.query // 响应类型是 query,不是 set
76
+ sendStructuredMessage(RoomPropertyEnum.set, sendData, resolve, error => reject(handleMqttError(error, 'Failed to set room property')), {
77
+ responseType: RoomPropertyEnum.query
78
+ } // 响应类型是 query,不是 set
77
79
  );
78
80
  } catch (error) {
79
81
  reject(handleMqttError(error, 'Failed to set room property'));
@@ -65,7 +65,9 @@ export const useSchedule = () => {
65
65
  if (useMqtt) {
66
66
  sendStructuredMessage(ScheduleEnum.set, _objectSpread(_objectSpread({}, message), {}, {
67
67
  list
68
- }), resolve, error => reject(handleMqttError(error, 'Failed to set schedule')), ScheduleEnum.query // 响应类型是 query,不是 set
68
+ }), resolve, error => reject(handleMqttError(error, 'Failed to set schedule')), {
69
+ responseType: ScheduleEnum.query
70
+ } // 响应类型是 query,不是 set
69
71
  );
70
72
  return;
71
73
  }
@@ -107,7 +107,9 @@ export const useSelectRoomClean = () => {
107
107
  routePreferences: prefs.map(p => p !== null && p !== void 0 ? p : 'standard')
108
108
  }), {}, {
109
109
  num: rooms.length
110
- }), resolve, error => reject(handleMqttError(error, 'Failed to set room clean')), RoomCleanSetEnum.query // 响应类型是 query,不是 set
110
+ }), resolve, error => reject(handleMqttError(error, 'Failed to set room clean')), {
111
+ responseType: RoomCleanSetEnum.query
112
+ } // 响应类型是 query,不是 set
111
113
  );
112
114
  return;
113
115
  }
@@ -80,7 +80,9 @@ export const useSpotClean = () => {
80
80
  names
81
81
  }), spotNames && {
82
82
  spotNames
83
- }), resolve, error => reject(handleMqttError(error, 'Failed to set spot clean')), SpotCleanEnum.query // 响应类型是 query,不是 set
83
+ }), resolve, error => reject(handleMqttError(error, 'Failed to set spot clean')), {
84
+ responseType: SpotCleanEnum.query
85
+ } // 响应类型是 query,不是 set
84
86
  );
85
87
  return;
86
88
  }
@@ -38,7 +38,9 @@ export const useSpotPolygons = () => {
38
38
  reject(new Error('useMqtt is not used'));
39
39
  return;
40
40
  }
41
- sendStructuredMessage(SpotPolygonsEnum.set, createSpotPolygonsPayload(message), resolve, error => reject(handleMqttError(error, 'Failed to set spot polygons')), SpotPolygonsEnum.query);
41
+ sendStructuredMessage(SpotPolygonsEnum.set, createSpotPolygonsPayload(message), resolve, error => reject(handleMqttError(error, 'Failed to set spot polygons')), {
42
+ responseType: SpotPolygonsEnum.query
43
+ });
42
44
  } catch (error) {
43
45
  reject(handleMqttError(error, 'Failed to set spot polygons'));
44
46
  }
@@ -0,0 +1,10 @@
1
+ import { type TRequestThreshold, type TSetThreshold } from './type/protocols';
2
+ /**
3
+ * 自定义 Hook,用于门槛管理(可通过门槛 / 不可通过门槛 / 坡道)
4
+ * 门槛协议仅支持 MQTT / LAN 结构化消息通道,未启用 useMqtt 时直接 reject
5
+ * @returns 包含 requestThreshold 和 setThreshold 函数的对象
6
+ */
7
+ export declare const useThreshold: () => {
8
+ requestThreshold: TRequestThreshold;
9
+ setThreshold: TSetThreshold;
10
+ };
@@ -0,0 +1,90 @@
1
+ import "core-js/modules/esnext.iterator.constructor.js";
2
+ import "core-js/modules/esnext.iterator.for-each.js";
3
+ // 门槛(可通过门槛 / 不可通过门槛 / 坡道)
4
+ import { useContext } from 'react';
5
+ import { pointsToString } from '../utils';
6
+ import { handleMqttError, useStructuredMessage } from './hooks/useStructuredMessage';
7
+ import { SingletonContext } from './mqttProvider';
8
+ import { ThresholdEnum } from './type';
9
+ // 门槛
10
+
11
+ /**
12
+ * 自定义 Hook,用于门槛管理(可通过门槛 / 不可通过门槛 / 坡道)
13
+ * 门槛协议仅支持 MQTT / LAN 结构化消息通道,未启用 useMqtt 时直接 reject
14
+ * @returns 包含 requestThreshold 和 setThreshold 函数的对象
15
+ */
16
+ export const useThreshold = () => {
17
+ const {
18
+ useMqtt
19
+ } = useContext(SingletonContext);
20
+ const {
21
+ sendStructuredMessage
22
+ } = useStructuredMessage();
23
+
24
+ /**
25
+ * 请求门槛数据
26
+ * @returns Promise<ThresholdResponse> 响应结果
27
+ */
28
+
29
+ /**
30
+ * 设置门槛数据(全量覆盖,传空数组表示清空全部门槛)
31
+ * @param message 包含门槛设置参数的对象
32
+ * @param message.data 门槛的数据数组,每项含 4 个顶点、类型与可选名称
33
+ * @param message.origin 原点坐标
34
+ * @returns Promise<ThresholdResponse> 响应结果
35
+ */
36
+
37
+ return {
38
+ requestThreshold: () => {
39
+ return new Promise((resolve, reject) => {
40
+ try {
41
+ if (!useMqtt) {
42
+ reject(new Error('useMqtt is not used'));
43
+ return;
44
+ }
45
+ sendStructuredMessage(ThresholdEnum.query, {}, resolve, error => reject(handleMqttError(error, 'Failed to request threshold')));
46
+ } catch (error) {
47
+ reject(handleMqttError(error, 'Failed to request threshold'));
48
+ }
49
+ });
50
+ },
51
+ setThreshold: message => {
52
+ return new Promise((resolve, reject) => {
53
+ try {
54
+ if (!useMqtt) {
55
+ reject(new Error('useMqtt is not used'));
56
+ return;
57
+ }
58
+ const {
59
+ data,
60
+ origin
61
+ } = message;
62
+ const polygons = [];
63
+ const types = [];
64
+ const names = [];
65
+ data.forEach(_ref => {
66
+ let {
67
+ points,
68
+ type,
69
+ name
70
+ } = _ref;
71
+ polygons.push(pointsToString(points, origin));
72
+ types.push(type);
73
+ names.push(name !== null && name !== void 0 ? name : '');
74
+ });
75
+ sendStructuredMessage(ThresholdEnum.set, {
76
+ num: data.length,
77
+ polygons,
78
+ types,
79
+ names
80
+ }, resolve, error => reject(handleMqttError(error, 'Failed to set threshold')), {
81
+ responseType: ThresholdEnum.query
82
+ } // 响应类型是 query,不是 set
83
+ );
84
+ } catch (error) {
85
+ reject(handleMqttError(error, 'Failed to set threshold'));
86
+ }
87
+ });
88
+ }
89
+ };
90
+ };
@@ -96,7 +96,9 @@ export const useVirtualArea = () => {
96
96
  num: data.length,
97
97
  modes: modes,
98
98
  names: names
99
- }, resolve, error => reject(handleMqttError(error, 'Failed to set virtual area')), VirtualAreaEnum.query // 响应类型是 query,不是 set
99
+ }, resolve, error => reject(handleMqttError(error, 'Failed to set virtual area')), {
100
+ responseType: VirtualAreaEnum.query
101
+ } // 响应类型是 query,不是 set
100
102
  );
101
103
  return;
102
104
  }
@@ -77,7 +77,9 @@ export const useVirtualWall = () => {
77
77
  points: data.map(points => pointsToString(points, origin)),
78
78
  num: data.length,
79
79
  mode: new Array(data.length).fill('0')
80
- }, resolve, error => reject(handleMqttError(error, 'Failed to set virtual wall')), VirtualWallEnum.query // 响应类型是 query,不是 set
80
+ }, resolve, error => reject(handleMqttError(error, 'Failed to set virtual wall')), {
81
+ responseType: VirtualWallEnum.query
82
+ } // 响应类型是 query,不是 set
81
83
  );
82
84
  return;
83
85
  }
@@ -71,7 +71,9 @@ export const useVoice = () => {
71
71
  const sendData = _objectSpread(_objectSpread({}, message), {}, {
72
72
  urlLen: message.url.length
73
73
  });
74
- sendStructuredMessage(VoiceLanguageEnum.set, sendData, resolve, error => reject(handleMqttError(error, 'Failed to set voice')), VoiceLanguageEnum.query);
74
+ sendStructuredMessage(VoiceLanguageEnum.set, sendData, resolve, error => reject(handleMqttError(error, 'Failed to set voice')), {
75
+ responseType: VoiceLanguageEnum.query
76
+ });
75
77
  return;
76
78
  }
77
79
 
@@ -41,7 +41,9 @@ export const useWifiMap = () => {
41
41
  taskId: data.taskId || String(Date.now()),
42
42
  switch: (_data$switch = data.switch) !== null && _data$switch !== void 0 ? _data$switch : true
43
43
  };
44
- sendStructuredMessage(WifiMapEnum.set, wifiMapData, resolve, error => reject(handleMqttError(error, 'Failed to set WiFi map')), WifiMapEnum.rst // 响应类型是 rst,不是 set
44
+ sendStructuredMessage(WifiMapEnum.set, wifiMapData, resolve, error => reject(handleMqttError(error, 'Failed to set WiFi map')), {
45
+ responseType: WifiMapEnum.rst
46
+ } // 响应类型是 rst,不是 set
45
47
  );
46
48
  } catch (error) {
47
49
  reject(handleMqttError(error, 'Failed to set WiFi map'));
@@ -131,7 +131,9 @@ export const useZoneClean = () => {
131
131
  polygons
132
132
  }, commonFields), {}, {
133
133
  names
134
- }), resolve, error => reject(handleMqttError(error, 'Failed to set zone clean')), ZoneCleanEnum.query);
134
+ }), resolve, error => reject(handleMqttError(error, 'Failed to set zone clean')), {
135
+ responseType: ZoneCleanEnum.query
136
+ });
135
137
  return;
136
138
  }
137
139
 
@@ -6,27 +6,27 @@ export declare const emitter: import("mitt").Emitter<Record<import("mitt").Event
6
6
  export declare const pointsToString: (points: Point[], origin?: Point) => string;
7
7
  export declare const isJSONString: (str: any) => boolean;
8
8
  export declare const parseJSON: (str: any) => any;
9
- export declare const logger: (type: 'warn' | 'error' | 'info', params: {
10
- [key: string]: any;
9
+ export declare const logger: (type: "warn" | "error" | "info", params: {
11
10
  msg: string;
12
- }, onLogger?: ((type: 'warn' | 'error' | 'info', v: string) => void) | undefined) => void;
11
+ [key: string]: any;
12
+ }, onLogger?: (type: "warn" | "error" | "info", v: string) => void) => void;
13
13
  /**
14
14
  * 创建绑定了 onLogger 的 logger 函数
15
15
  * @param onLogger - 可选的日志回调函数
16
16
  * @returns 返回一个简化的 logger 函数
17
17
  */
18
- export declare const createLogger: (onLogger?: ((type: 'warn' | 'error' | 'info', v: string) => void) | undefined) => {
18
+ export declare const createLogger: (onLogger?: (type: "warn" | "error" | "info", v: string) => void) => {
19
19
  info: (params: {
20
- [key: string]: any;
21
20
  msg: string;
21
+ [key: string]: any;
22
22
  }) => void;
23
23
  warn: (params: {
24
- [key: string]: any;
25
24
  msg: string;
25
+ [key: string]: any;
26
26
  }) => void;
27
27
  error: (params: {
28
- [key: string]: any;
29
28
  msg: string;
29
+ [key: string]: any;
30
30
  }) => void;
31
31
  };
32
32
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ray-js/robot-data-stream",
3
- "version": "0.0.17-beta.9",
3
+ "version": "0.1.0-beta.0",
4
4
  "description": "扫地机P2P数据流标准化组件",
5
5
  "main": "lib/index",
6
6
  "files": [
@@ -17,6 +17,8 @@
17
17
  ],
18
18
  "scripts": {
19
19
  "lint": "eslint src --ext .js,.jsx,.ts,.tsx --fix",
20
+ "test": "vitest --run",
21
+ "typecheck": "tsc -p tsconfig.typecheck.json",
20
22
  "build": "patch-package && ray build --type=component",
21
23
  "watch": "ray start --type=component --output ./example/src/lib",
22
24
  "build:tuya": "ray build ./example",
@@ -63,6 +65,8 @@
63
65
  "patch-package": "^8.0.0",
64
66
  "prettier": "^3.8.0",
65
67
  "standard-version": "9.3.2",
68
+ "typescript": "^5.0.0",
69
+ "vitest": "^2.1.4",
66
70
  "vitepress": "^1.6.4"
67
71
  },
68
72
  "husky": {