@ray-js/lock-sdk 1.2.0-beta.1 → 1.2.0-beta.11

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 (81) hide show
  1. package/lib/api/index.d.ts +3 -1
  2. package/lib/api/index.js +16 -0
  3. package/lib/api/notify.d.ts +28 -0
  4. package/lib/api/notify.js +17 -0
  5. package/lib/api/screen.d.ts +1 -0
  6. package/lib/api/service.d.ts +26 -0
  7. package/lib/api/service.js +25 -0
  8. package/lib/api/video.d.ts +9 -0
  9. package/lib/api/video.js +30 -0
  10. package/lib/api/voip.d.ts +10 -0
  11. package/lib/api/voip.js +17 -0
  12. package/lib/config/dp-code/index.d.ts +1 -0
  13. package/lib/config/dp-code/index.js +1 -0
  14. package/lib/config/dp-map/media.d.ts +13 -0
  15. package/lib/config/dp-map/media.js +19 -0
  16. package/lib/entries/fit/index.js +1 -1
  17. package/lib/entries/main/bootstrap/bootstrap.js +1 -0
  18. package/lib/entries/main/exports/ai.d.ts +4 -0
  19. package/lib/entries/main/exports/ai.js +11 -0
  20. package/lib/entries/main/exports/index.d.ts +4 -0
  21. package/lib/entries/main/exports/index.js +4 -0
  22. package/lib/entries/main/exports/media.d.ts +10 -1
  23. package/lib/entries/main/exports/media.js +29 -1
  24. package/lib/entries/main/exports/misc.d.ts +1 -1
  25. package/lib/entries/main/exports/notify.d.ts +7 -0
  26. package/lib/entries/main/exports/notify.js +8 -0
  27. package/lib/entries/main/exports/screen/bind.d.ts +6 -3
  28. package/lib/entries/main/exports/screen/bind.js +7 -0
  29. package/lib/entries/main/exports/service.d.ts +4 -0
  30. package/lib/entries/main/exports/service.js +11 -0
  31. package/lib/entries/main/exports/voip.d.ts +3 -0
  32. package/lib/entries/main/exports/voip.js +8 -0
  33. package/lib/entries/main/index.js +1 -1
  34. package/lib/entries/screen/exports/bind-events.d.ts +4 -0
  35. package/lib/entries/screen/exports/bind-events.js +8 -0
  36. package/lib/entries/screen/exports/index.d.ts +1 -0
  37. package/lib/entries/screen/exports/index.js +1 -0
  38. package/lib/feature/ai/report.d.ts +5 -0
  39. package/lib/feature/ai/report.js +37 -0
  40. package/lib/feature/media/camera.d.ts +18 -0
  41. package/lib/feature/media/camera.js +36 -0
  42. package/lib/feature/media/media.d.ts +10 -0
  43. package/lib/feature/media/media.js +31 -0
  44. package/lib/feature/misc/capability.js +63 -6
  45. package/lib/feature/misc/connect-device.js +2 -1
  46. package/lib/feature/notify/notify.d.ts +4 -0
  47. package/lib/feature/notify/notify.js +3 -0
  48. package/lib/feature/password/temporary/custom-dp.js +59 -54
  49. package/lib/feature/screen/bind-watch.d.ts +18 -0
  50. package/lib/feature/screen/bind-watch.js +92 -0
  51. package/lib/feature/screen/bind.d.ts +2 -2
  52. package/lib/feature/screen/bind.js +8 -38
  53. package/lib/feature/screen/list.js +13 -0
  54. package/lib/feature/service/goto-service.d.ts +3 -2
  55. package/lib/feature/service/goto-service.js +7 -1
  56. package/lib/feature/service/value-added.d.ts +4 -0
  57. package/lib/feature/service/value-added.js +4 -0
  58. package/lib/feature/state/device-status.js +2 -2
  59. package/lib/feature/state/init-state.js +26 -18
  60. package/lib/feature/state/remote-permissions.js +16 -0
  61. package/lib/feature/storage/index.d.ts +5 -0
  62. package/lib/feature/storage/index.js +32 -0
  63. package/lib/feature/unlock/sync/unlock-method.js +3 -0
  64. package/lib/feature/voip/voip.d.ts +3 -0
  65. package/lib/feature/voip/voip.js +3 -0
  66. package/lib/interface.d.ts +25 -1
  67. package/lib/platform/device.d.ts +5 -4
  68. package/lib/platform/device.js +1 -1
  69. package/lib/platform/index.d.ts +1 -0
  70. package/lib/platform/index.js +1 -0
  71. package/lib/platform/ipc.d.ts +3 -0
  72. package/lib/platform/ipc.js +23 -7
  73. package/lib/platform/storage.d.ts +3 -0
  74. package/lib/platform/storage.js +9 -0
  75. package/lib/runtime/lock-config.d.ts +3 -1
  76. package/lib/runtime/lock-config.js +2 -0
  77. package/lib/utils/errors.js +3 -1
  78. package/lib/utils/index.d.ts +35 -0
  79. package/lib/utils/index.js +11 -1
  80. package/lib/utils/parse.js +1 -1
  81. package/package.json +1 -1
@@ -1,4 +1,5 @@
1
1
  import type { LockDeviceRuntime } from "../../runtime/LockDeviceRuntime";
2
+ import { MediaViewTimesResult, getAlbumDateListResult } from "../../api/video";
2
3
  export interface GetMediaUrlParams {
3
4
  mediaPath: string;
4
5
  mediaBucket: string;
@@ -19,6 +20,12 @@ export interface OpenLocalAlbumParams {
19
20
  serviceCode?: string;
20
21
  }
21
22
  export declare const openLocalAlbumForRuntime: (runtime: LockDeviceRuntime, params?: OpenLocalAlbumParams) => Promise<void>;
23
+ export interface GotoPlaybackParams {
24
+ tabs?: ("local" | "cloud")[];
25
+ isLowPower?: boolean;
26
+ rotate?: number;
27
+ }
28
+ export declare const gotoPlaybackForRuntime: (runtime: LockDeviceRuntime, params?: GotoPlaybackParams) => Promise<void>;
22
29
  export interface MediaInfo {
23
30
  imageAngle: number;
24
31
  videoAngle: number;
@@ -29,3 +36,6 @@ export interface MediaInfo {
29
36
  isTwoWayTalk: boolean;
30
37
  }
31
38
  export declare const getMediaInfoForRuntime: (runtime: LockDeviceRuntime) => MediaInfo;
39
+ export declare const getMediaViewTimesForRuntime: (runtime: LockDeviceRuntime) => Promise<MediaViewTimesResult>;
40
+ export declare const setMediaViewTimesForRuntime: (runtime: LockDeviceRuntime) => Promise<MediaViewTimesResult>;
41
+ export declare const getAlbumDateListForRuntime: (runtime: LockDeviceRuntime) => Promise<getAlbumDateListResult>;
@@ -4,6 +4,7 @@ import dpCodes from "../../config/dp-code";
4
4
  import { RotateType, VedioType } from "../../constant";
5
5
  import { isSupportShortLink } from "../../platform";
6
6
  import { getError } from "../../utils/errors";
7
+ import { getMediaViewTimes, setMediaViewTimes, getAlbumDateList, } from "../../api/video";
7
8
  export const getMediaUrlForRuntime = async (runtime, params) => {
8
9
  const devId = runtime.config.devInfo.devId;
9
10
  if ("mediaPath" in params && "mediaBucket" in params) {
@@ -52,6 +53,27 @@ export const openLocalAlbumForRuntime = async (runtime, params) => {
52
53
  }
53
54
  return Promise.reject(getError(1013));
54
55
  };
56
+ export const gotoPlaybackForRuntime = async (runtime, params) => {
57
+ const link = await isSupportShortLink("camera_playbacks_panel");
58
+ if (!link) {
59
+ return Promise.reject(getError(1013));
60
+ }
61
+ const tabs = params?.tabs && params.tabs.length ? params.tabs : ["local"];
62
+ let url = `tuyaSmart://${link}?extra_camera_uuid=${runtime.devId}&devId=${runtime.devId}&bizType=doorLock&defaultShowTabs=true&theme=1&tabs=${JSON.stringify(tabs)}`;
63
+ if (params?.isLowPower) {
64
+ url += `&isLowPowerDevice=true`;
65
+ }
66
+ if (params?.rotate !== undefined) {
67
+ url += `&rotate=${params.rotate}`;
68
+ }
69
+ return new Promise((resolve, reject) => {
70
+ ty.router({
71
+ url,
72
+ success: () => resolve(),
73
+ fail: (e) => reject(e),
74
+ });
75
+ });
76
+ };
55
77
  export const getMediaInfoForRuntime = (runtime) => {
56
78
  const isSEI = runtime.config.capabilities?.rotateType === RotateType.SEI;
57
79
  return {
@@ -64,3 +86,12 @@ export const getMediaInfoForRuntime = (runtime) => {
64
86
  isTwoWayTalk: runtime.config.isTwoWayTalk,
65
87
  };
66
88
  };
89
+ export const getMediaViewTimesForRuntime = (runtime) => {
90
+ return getMediaViewTimes(runtime.config.devInfo.devId);
91
+ };
92
+ export const setMediaViewTimesForRuntime = (runtime) => {
93
+ return setMediaViewTimes(runtime.config.devInfo.devId);
94
+ };
95
+ export const getAlbumDateListForRuntime = (runtime) => {
96
+ return getAlbumDateList(runtime.config.devInfo.devId);
97
+ };
@@ -1,6 +1,7 @@
1
1
  import { getDeviceAdvancedAbility, getProductAbilities } from "../../api";
2
2
  import { ProductCommunicationType } from "../../constant";
3
3
  import { checkShowMatterMutilpleShare } from "../../platform/device";
4
+ import { ipc } from "../../platform";
4
5
  export const hasCapabilityForRuntime = (runtime, capability) => runtime.config.communication.includes(capability);
5
6
  export const isBlePureDeviceForRuntime = (rt) => hasCapabilityForRuntime(rt, ProductCommunicationType.BLUETOOTH) &&
6
7
  rt.config.communication.length === 1;
@@ -34,23 +35,54 @@ export const isActiveThreadForRuntime = async (rt) => {
34
35
  }
35
36
  return false;
36
37
  };
38
+ const allModes = [
39
+ {
40
+ mode: "VR",
41
+ value: 1,
42
+ },
43
+ {
44
+ mode: "original",
45
+ value: 0,
46
+ },
47
+ {
48
+ mode: "vertical",
49
+ value: 3,
50
+ },
51
+ {
52
+ mode: "horizontal",
53
+ value: 2,
54
+ },
55
+ ];
37
56
  export const getDeviceAdvancedAbilitiesForRuntime = async (rt) => {
38
57
  if (rt.cache.deviceAdvanceAbilityCache) {
39
58
  return rt.cache.deviceAdvanceAbilityCache;
40
59
  }
41
- const [productAbilities, deviceAdvancedAbility] = await Promise.all([
60
+ const [productAbilitiesRes, deviceAdvancedAbilityRes, tttList] = await Promise.allSettled([
42
61
  getProductAbilities(rt.config.devInfo.devId, [
43
62
  "tyabi4ucx5",
44
63
  "tyabis9tpe",
45
64
  "tyabiwxrn9",
46
65
  "tyabipd4hh",
47
66
  "tyabin4u5v",
67
+ "visual_door_lock_cloud_store",
48
68
  ]),
49
69
  getDeviceAdvancedAbility(rt.config.devInfo.devId),
70
+ ipc.getTTTAbilityKeyList("isSupportedVRMode"),
50
71
  ]);
72
+ const productAbilities = productAbilitiesRes.status === "fulfilled" ? productAbilitiesRes.value : [];
73
+ const deviceAdvancedAbility = deviceAdvancedAbilityRes.status === "fulfilled"
74
+ ? deviceAdvancedAbilityRes.value
75
+ : undefined;
76
+ const tttAbList = tttList.status === "fulfilled" ? tttList.value.abilityList : [];
51
77
  const deviceAdvanceAbilityCache = {
52
78
  cloudStorage: {
53
- support: deviceAdvancedAbility.types.includes(0),
79
+ support: deviceAdvancedAbility?.types?.includes(0) ?? false,
80
+ },
81
+ vr: {
82
+ support: false,
83
+ defaultMode: "VR",
84
+ modes: [],
85
+ coverMode: "VR",
54
86
  },
55
87
  ai: {
56
88
  support: false,
@@ -61,12 +93,12 @@ export const getDeviceAdvancedAbilitiesForRuntime = async (rt) => {
61
93
  config: {},
62
94
  },
63
95
  voip: {
64
- support: deviceAdvancedAbility.types.includes(1),
96
+ support: false,
65
97
  config: {},
66
98
  },
67
99
  wechatVoip: {
68
100
  support: false,
69
- config: {},
101
+ isPublice: true,
70
102
  },
71
103
  unlockGuide: {
72
104
  support: false,
@@ -80,8 +112,11 @@ export const getDeviceAdvancedAbilitiesForRuntime = async (rt) => {
80
112
  productAbilities.forEach((item) => {
81
113
  try {
82
114
  if (item.isOpen) {
83
- const data = JSON.parse(item.extConfig);
115
+ const data = item.extConfig ? JSON.parse(item.extConfig) : {};
84
116
  switch (item.abilityCode) {
117
+ case "visual_door_lock_cloud_store":
118
+ deviceAdvanceAbilityCache.cloudStorage.support = true;
119
+ break;
85
120
  case "tyabi4ucx5": {
86
121
  deviceAdvanceAbilityCache.ai.config = data;
87
122
  const dataReport = data?.ai_data_report ?? false;
@@ -95,6 +130,20 @@ export const getDeviceAdvancedAbilitiesForRuntime = async (rt) => {
95
130
  petRecognition ||
96
131
  voice ||
97
132
  message;
133
+ deviceAdvanceAbilityCache.vr.support =
134
+ !!data?.lock_VR && tttAbList.length > 0;
135
+ if (deviceAdvanceAbilityCache.vr.support) {
136
+ deviceAdvanceAbilityCache.vr.modes = allModes.filter((item) => {
137
+ return data?.modes?.includes(item.mode);
138
+ });
139
+ deviceAdvanceAbilityCache.vr.defaultMode = data.default_mode;
140
+ const exist = deviceAdvanceAbilityCache.vr.modes.find((x) => x.mode === deviceAdvanceAbilityCache.vr.defaultMode);
141
+ if (!exist) {
142
+ deviceAdvanceAbilityCache.vr.defaultMode =
143
+ deviceAdvanceAbilityCache.vr.modes?.[0]?.mode;
144
+ }
145
+ deviceAdvanceAbilityCache.vr.coverMode = data.photo_cover_format;
146
+ }
98
147
  break;
99
148
  }
100
149
  case "tyabis9tpe": {
@@ -104,8 +153,16 @@ export const getDeviceAdvancedAbilitiesForRuntime = async (rt) => {
104
153
  }
105
154
  case "tyabiwxrn9": {
106
155
  deviceAdvanceAbilityCache.wechatVoip.support =
156
+ deviceAdvancedAbility?.types?.includes(1) ?? false;
157
+ deviceAdvanceAbilityCache.wechatVoip.isPublice =
158
+ data?.WechatType === "0";
159
+ if (!deviceAdvanceAbilityCache.wechatVoip.isPublice) {
160
+ deviceAdvanceAbilityCache.wechatVoip.appId =
161
+ data["WechatMPAppid"];
162
+ deviceAdvanceAbilityCache.wechatVoip.modeId = data["WechatMPMid"];
163
+ }
164
+ deviceAdvanceAbilityCache.voip.support =
107
165
  !!data?.voipType?.includes("0");
108
- deviceAdvanceAbilityCache.wechatVoip.config = data;
109
166
  break;
110
167
  }
111
168
  case "tyabipd4hh": {
@@ -154,10 +154,11 @@ export async function connectDeviceForRuntime(rt) {
154
154
  data: {
155
155
  statusType: deviceStatus.type,
156
156
  onlineTypes: deviceStatus.onlineTypes,
157
+ connectEnable: deviceStatus.connectEnable,
157
158
  hasWirelessAwakeDp,
158
159
  },
159
160
  });
160
- if (hasWirelessAwakeDp) {
161
+ if (deviceStatus.connectEnable && hasWirelessAwakeDp) {
161
162
  if (cfg.devInfo.isCloudOnline && !getDpValueForRuntime(rt, wirelessAwake)) {
162
163
  const result = await awakeDevice(devId);
163
164
  sdkLog("info", "connectDevice", "success", {
@@ -0,0 +1,4 @@
1
+ import { type UpdateVasNotifyConfigParams } from "../../api/notify";
2
+ import type { LockDeviceRuntime } from "../../runtime/LockDeviceRuntime";
3
+ export declare const getVasNotifyConfigForRuntime: (rt: LockDeviceRuntime) => Promise<import("../../api/notify").VasNotifyConfig>;
4
+ export declare const updateVasNotifyConfigForRuntime: (rt: LockDeviceRuntime, params: UpdateVasNotifyConfigParams) => Promise<import("../../api/notify").VasNotifyConfig>;
@@ -0,0 +1,3 @@
1
+ import { getVasNotifyConfigApi, updateVasNotifyConfigApi, } from "../../api/notify";
2
+ export const getVasNotifyConfigForRuntime = (rt) => getVasNotifyConfigApi(rt.config.devInfo.devId);
3
+ export const updateVasNotifyConfigForRuntime = (rt, params) => updateVasNotifyConfigApi(rt.config.devInfo.devId, params);
@@ -52,67 +52,72 @@ export const createTempCustomForRuntime = parallelOnlyForRuntime(async function
52
52
  throw handleCloudError(error);
53
53
  }
54
54
  }
55
- await isValidPassword(baseData);
56
- const { tyNum, name: createdName } = await createTemporaryPassword({
57
- ...baseData,
58
- sn: 0,
59
- availTime: 0,
60
- symbolic: false,
61
- dpTunnel: 2,
62
- });
63
- if (!tyNum) {
64
- const error = getError(1043);
65
- sdkLog("warn", "tempPassword", "createCustomMissingCloudNo", {
55
+ try {
56
+ await isValidPassword(baseData);
57
+ const { tyNum, name: createdName } = await createTemporaryPassword({
58
+ ...baseData,
59
+ sn: 0,
60
+ availTime: 0,
61
+ symbolic: false,
62
+ dpTunnel: 2,
63
+ });
64
+ if (!tyNum) {
65
+ const error = getError(1043);
66
+ sdkLog("warn", "tempPassword", "createCustomMissingCloudNo", {
67
+ devId: rt.devId,
68
+ duration: Date.now() - startedAt,
69
+ error,
70
+ });
71
+ throw error;
72
+ }
73
+ const targetDpCode = cfg.supportBigData
74
+ ? dpCodes.tempPwdCreateW
75
+ : dpCodes.tempPwdCreate;
76
+ const dpPayload = dpUtils.format({
77
+ cloudNo: tyNum,
78
+ valid: true,
79
+ validConfig,
80
+ validNum: 0,
81
+ pwdLength: params.password.length,
82
+ pwd: params.password.split("").map(Number),
83
+ }, (cfg.supportBigData ? addTempPwdBigDpMap : addTempPwdDpMap));
84
+ const result = await publishDpsForRuntime(rt, {
85
+ [targetDpCode]: dpPayload,
86
+ }, {
87
+ checkReport: (dpsIn) => {
88
+ const dpDataRow = dpsIn;
89
+ const reportData = dpDataRow[targetDpCode];
90
+ if (reportData) {
91
+ const data = dpUtils.parse(dpDataRow[targetDpCode], (cfg.supportBigData
92
+ ? reportAddTempPwdDBigpMap
93
+ : reportAddTempPwdDpMap));
94
+ if (data.cloudNo === tyNum) {
95
+ return data;
96
+ }
97
+ }
98
+ return false;
99
+ },
100
+ });
101
+ if (result.status === 0) {
102
+ sdkLog("info", "tempPassword", "createCustomSuccess", {
103
+ devId: rt.devId,
104
+ duration: Date.now() - startedAt,
105
+ data: { route: "nearDp" },
106
+ });
107
+ return buildTempCustomCreateResult(createdName, params.password, result.unlockBindingId, effective);
108
+ }
109
+ const error = getError(result.status === 2 ? 1041 : 1042);
110
+ sdkLog("warn", "tempPassword", "createCustomDpFail", {
66
111
  devId: rt.devId,
67
112
  duration: Date.now() - startedAt,
113
+ data: { status: result.status },
68
114
  error,
69
115
  });
70
116
  throw error;
71
117
  }
72
- const targetDpCode = cfg.supportBigData
73
- ? dpCodes.tempPwdCreateW
74
- : dpCodes.tempPwdCreate;
75
- const dpPayload = dpUtils.format({
76
- cloudNo: tyNum,
77
- valid: true,
78
- validConfig,
79
- validNum: 0,
80
- pwdLength: params.password.length,
81
- pwd: params.password.split("").map(Number),
82
- }, (cfg.supportBigData ? addTempPwdBigDpMap : addTempPwdDpMap));
83
- const result = await publishDpsForRuntime(rt, {
84
- [targetDpCode]: dpPayload,
85
- }, {
86
- checkReport: (dpsIn) => {
87
- const dpDataRow = dpsIn;
88
- const reportData = dpDataRow[targetDpCode];
89
- if (reportData) {
90
- const data = dpUtils.parse(dpDataRow[targetDpCode], (cfg.supportBigData
91
- ? reportAddTempPwdDBigpMap
92
- : reportAddTempPwdDpMap));
93
- if (data.cloudNo === tyNum) {
94
- return data;
95
- }
96
- }
97
- return false;
98
- },
99
- });
100
- if (result.status === 0) {
101
- sdkLog("info", "tempPassword", "createCustomSuccess", {
102
- devId: rt.devId,
103
- duration: Date.now() - startedAt,
104
- data: { route: "nearDp" },
105
- });
106
- return buildTempCustomCreateResult(createdName, params.password, result.unlockBindingId, effective);
118
+ catch (er) {
119
+ throw handleCloudError(er);
107
120
  }
108
- const error = getError(result.status === 2 ? 1041 : 1042);
109
- sdkLog("warn", "tempPassword", "createCustomDpFail", {
110
- devId: rt.devId,
111
- duration: Date.now() - startedAt,
112
- data: { status: result.status },
113
- error,
114
- });
115
- throw error;
116
121
  });
117
122
  export async function removeTempCustomForRuntime(rt, params) {
118
123
  const cfg = rt.config;
@@ -0,0 +1,18 @@
1
+ import { type BindingResult } from "../../api/screen";
2
+ import type { ErrorData } from "../../interface";
3
+ import type { LockDeviceRuntime } from "../../runtime/LockDeviceRuntime";
4
+ export interface BindLockToScreenEvent {
5
+ lockDevId: string;
6
+ success: boolean;
7
+ data?: BindingResult;
8
+ error?: ErrorData;
9
+ }
10
+ export type BindLockToScreenListener = (event: BindLockToScreenEvent) => void;
11
+ export declare function emitBindResult(runtime: LockDeviceRuntime, event: BindLockToScreenEvent): void;
12
+ export declare function onBindLockToScreenForRuntime(runtime: LockDeviceRuntime, listener: BindLockToScreenListener): void;
13
+ export declare function offBindLockToScreenForRuntime(runtime: LockDeviceRuntime, listener: BindLockToScreenListener): void;
14
+ export declare function watchBindResult(runtime: LockDeviceRuntime, params: {
15
+ lockDevId: string;
16
+ sessionId: string;
17
+ }): Promise<void>;
18
+ export declare function isWatchingBind(runtime: LockDeviceRuntime, sessionId: string): boolean;
@@ -0,0 +1,92 @@
1
+ import { getBindingResultApi } from "../../api/screen";
2
+ import emitter from "../../utils/event";
3
+ import { getError } from "../../utils/errors";
4
+ import { sdkLog } from "../../utils/sdk-log";
5
+ import { handleScreenCloudError } from "./error";
6
+ const POLL_INTERVAL_MS = 2_000;
7
+ const BIND_POLL_TIMEOUT_MS = 30_000;
8
+ const delay = (ms) => new Promise((resolve) => {
9
+ setTimeout(resolve, ms);
10
+ });
11
+ function bindResultEventName(runtime) {
12
+ return `screen_bind_result_${runtime.devId}`;
13
+ }
14
+ export function emitBindResult(runtime, event) {
15
+ emitter.emit(bindResultEventName(runtime), event);
16
+ }
17
+ const watchKey = (runtime, sessionId) => `${runtime.devId}:${sessionId}`;
18
+ const inflight = new Map();
19
+ export function onBindLockToScreenForRuntime(runtime, listener) {
20
+ emitter.on(bindResultEventName(runtime), listener);
21
+ }
22
+ export function offBindLockToScreenForRuntime(runtime, listener) {
23
+ emitter.off(bindResultEventName(runtime), listener);
24
+ }
25
+ async function pollBindResult(runtime, lockDevId, sessionId) {
26
+ const accessoryDevId = runtime.devId;
27
+ const startedAt = Date.now();
28
+ const deadline = startedAt + BIND_POLL_TIMEOUT_MS;
29
+ while (Date.now() < deadline) {
30
+ await delay(POLL_INTERVAL_MS);
31
+ let result;
32
+ try {
33
+ result = await getBindingResultApi({ accessoryDevId, sessionId });
34
+ }
35
+ catch (e) {
36
+ const error = handleScreenCloudError(e);
37
+ sdkLog("error", "screen", "bindResultPollError", {
38
+ devId: accessoryDevId,
39
+ duration: Date.now() - startedAt,
40
+ data: { lockDevId },
41
+ error: e,
42
+ });
43
+ emitBindResult(runtime, { lockDevId, success: false, error });
44
+ return;
45
+ }
46
+ if (result.status === "binding") {
47
+ continue;
48
+ }
49
+ if (result.status === "bound") {
50
+ sdkLog("info", "screen", "bindResultSettled", {
51
+ devId: accessoryDevId,
52
+ duration: Date.now() - startedAt,
53
+ data: { lockDevId, status: result.status, lanStatus: result.lanStatus },
54
+ });
55
+ emitBindResult(runtime, { lockDevId, success: true, data: result });
56
+ return;
57
+ }
58
+ sdkLog("info", "screen", "bindResultSettled", {
59
+ devId: accessoryDevId,
60
+ duration: Date.now() - startedAt,
61
+ data: { lockDevId, status: result.status, lanStatus: result.lanStatus },
62
+ });
63
+ emitBindResult(runtime, {
64
+ lockDevId,
65
+ success: false,
66
+ data: result,
67
+ error: getError(1103),
68
+ });
69
+ return;
70
+ }
71
+ sdkLog("warn", "screen", "bindResultTimeout", {
72
+ devId: accessoryDevId,
73
+ duration: Date.now() - startedAt,
74
+ data: { lockDevId },
75
+ });
76
+ emitBindResult(runtime, { lockDevId, success: false, error: getError(1002) });
77
+ }
78
+ export function watchBindResult(runtime, params) {
79
+ const key = watchKey(runtime, params.sessionId);
80
+ const existing = inflight.get(key);
81
+ if (existing) {
82
+ return existing;
83
+ }
84
+ const task = pollBindResult(runtime, params.lockDevId, params.sessionId).finally(() => {
85
+ inflight.delete(key);
86
+ });
87
+ inflight.set(key, task);
88
+ return task;
89
+ }
90
+ export function isWatchingBind(runtime, sessionId) {
91
+ return inflight.has(watchKey(runtime, sessionId));
92
+ }
@@ -1,4 +1,4 @@
1
- import { type BindingResult, type UnbindingResult } from "../../api/screen";
1
+ import { type AddBindingResult, type UnbindingResult } from "../../api/screen";
2
2
  import type { LockDeviceRuntime } from "../../runtime/LockDeviceRuntime";
3
- export declare function bindLockForRuntime(runtime: LockDeviceRuntime, lockDevId: string): Promise<BindingResult>;
3
+ export declare function bindLockForRuntime(runtime: LockDeviceRuntime, lockDevId: string): Promise<AddBindingResult>;
4
4
  export declare function unbindLockForRuntime(runtime: LockDeviceRuntime, relationId: string): Promise<UnbindingResult>;
@@ -1,11 +1,11 @@
1
- import { addBindingApi, deleteBindingApi, getBindingResultApi, getUnbindingResultApi, } from "../../api/screen";
1
+ import { addBindingApi, deleteBindingApi, getUnbindingResultApi, } from "../../api/screen";
2
2
  import { getDeviceInfo } from "../../platform/device";
3
3
  import { getError } from "../../utils/errors";
4
4
  import { sdkLog } from "../../utils/sdk-log";
5
5
  import { getDeviceStatusForRuntime } from "../state/device-status";
6
6
  import { handleScreenCloudError } from "./error";
7
+ import { watchBindResult } from "./bind-watch";
7
8
  const POLL_INTERVAL_MS = 2_000;
8
- const BIND_POLL_TIMEOUT_MS = 25_000;
9
9
  const UNBIND_POLL_TIMEOUT_MS = 20_000;
10
10
  const delay = (ms) => new Promise((resolve) => {
11
11
  setTimeout(resolve, ms);
@@ -42,48 +42,18 @@ export async function bindLockForRuntime(runtime, lockDevId) {
42
42
  });
43
43
  sdkLog("info", "screen", "bindAddSuccess", {
44
44
  devId: accessoryDevId,
45
+ duration: Date.now() - startedAt,
45
46
  data: { lockDevId, relationId: sessionData.relationId },
46
47
  });
47
48
  }
48
49
  catch (e) {
49
50
  throw handleScreenCloudError(e);
50
51
  }
51
- const deadline = Date.now() + BIND_POLL_TIMEOUT_MS;
52
- let last;
53
- while (Date.now() < deadline) {
54
- await delay(POLL_INTERVAL_MS);
55
- try {
56
- last = await getBindingResultApi({
57
- accessoryDevId,
58
- sessionId: sessionData.sessionId,
59
- });
60
- }
61
- catch (e) {
62
- throw handleScreenCloudError(e);
63
- }
64
- if (last.status !== "binding") {
65
- sdkLog("info", "screen", "bindSettled", {
66
- devId: accessoryDevId,
67
- duration: Date.now() - startedAt,
68
- data: {
69
- lockDevId,
70
- relationId: sessionData.relationId,
71
- status: last.status,
72
- lanStatus: last.lanStatus,
73
- },
74
- });
75
- if (last.status === "failed") {
76
- throw getError(1103);
77
- }
78
- return last;
79
- }
80
- }
81
- sdkLog("warn", "screen", "bindTimeout", {
82
- devId: accessoryDevId,
83
- duration: Date.now() - startedAt,
84
- data: { lockDevId, relationId: sessionData.relationId },
85
- });
86
- throw getError(1002);
52
+ void watchBindResult(runtime, {
53
+ lockDevId,
54
+ sessionId: sessionData.sessionId,
55
+ }).catch(() => { });
56
+ return sessionData;
87
57
  }
88
58
  catch (error) {
89
59
  sdkLog("error", "screen", "bindFail", {
@@ -1,6 +1,7 @@
1
1
  import { getBoundLockListApi, getBindableLockListApi, } from "../../api/screen";
2
2
  import { getDeviceInfo } from "../../platform/device";
3
3
  import { sdkLog } from "../../utils/sdk-log";
4
+ import { isWatchingBind, watchBindResult } from "./bind-watch";
4
5
  async function resolveLockDeviceInfo(accessoryDevId, lockDevId) {
5
6
  try {
6
7
  const info = await getDeviceInfo(lockDevId);
@@ -52,5 +53,17 @@ export async function getBindableLockListForRuntime(runtime) {
52
53
  duration: Date.now() - startedAt,
53
54
  data: { count: items.length, canBindMore: result?.canBindMore },
54
55
  });
56
+ for (const item of items) {
57
+ if (item.bindStatus !== "binding" || !item.sessionId) {
58
+ continue;
59
+ }
60
+ if (isWatchingBind(runtime, item.sessionId)) {
61
+ continue;
62
+ }
63
+ void watchBindResult(runtime, {
64
+ lockDevId: item.lockDevId,
65
+ sessionId: item.sessionId,
66
+ }).catch(() => { });
67
+ }
55
68
  return { ...result, items };
56
69
  }
@@ -1,5 +1,6 @@
1
1
  import type { LockDeviceRuntime } from "../../runtime/LockDeviceRuntime";
2
2
  export interface GotoServiceParams {
3
- tab?: "cloudStorage" | "AI";
3
+ tab?: "cloudStorage" | "AI" | "voip";
4
+ showGift?: boolean;
4
5
  }
5
- export declare function gotoServiceForRuntime(rt: LockDeviceRuntime, params?: GotoServiceParams): Promise<unknown>;
6
+ export declare function gotoServiceForRuntime(rt: LockDeviceRuntime, params?: GotoServiceParams): Promise<void>;
@@ -4,8 +4,14 @@ export function gotoServiceForRuntime(rt, params) {
4
4
  if (params?.tab === "AI") {
5
5
  type = 3;
6
6
  }
7
+ else if (params?.tab === "voip") {
8
+ type = 1;
9
+ }
7
10
  return new Promise((resolve, reject) => {
8
- const url = `godzilla://tyawqoyej4wi3pqebb?deviceId=${rt.config.devInfo.devId}&commodityType=${type}`;
11
+ let url = `godzilla://tyawqoyej4wi3pqebb?deviceId=${rt.config.devInfo.devId}&commodityType=${type}`;
12
+ if (params?.showGift) {
13
+ url += `&showGift=true`;
14
+ }
9
15
  navigateToMiniProgram({
10
16
  position: "bottom",
11
17
  shortLink: url,
@@ -0,0 +1,4 @@
1
+ import type { LockDeviceRuntime } from "../../runtime/LockDeviceRuntime";
2
+ export declare const getCloudServiceStatusForRuntime: (rt: LockDeviceRuntime) => Promise<import("../../api/service").CloudServiceStatus>;
3
+ export declare const getServicePopupListForRuntime: (rt: LockDeviceRuntime) => Promise<import("../../api/service").ServiceBenefitPopupItem[]>;
4
+ export declare const claimServiceForRuntime: (rt: LockDeviceRuntime, batchId: string) => Promise<import("../../api/service").ClaimResultItem[]>;
@@ -0,0 +1,4 @@
1
+ import { getCloudServiceStatusApi, getServicePopupListApi, claimServiceApi, } from "../../api/service";
2
+ export const getCloudServiceStatusForRuntime = (rt) => getCloudServiceStatusApi(rt.config.devInfo.devId);
3
+ export const getServicePopupListForRuntime = (rt) => getServicePopupListApi(rt.config.devInfo.devId);
4
+ export const claimServiceForRuntime = (rt, batchId) => claimServiceApi(rt.config.devInfo.devId, batchId);
@@ -23,7 +23,7 @@ export const updateOnlineType = async (runtime) => {
23
23
  updateDeviceStatus(runtime);
24
24
  };
25
25
  export const getDeviceStatusForRuntime = (runtime) => {
26
- const { onlineType, devInfo: { isCloudOnline, isOnline, wifiEnableState, isMatter }, } = runtime.config;
26
+ const { onlineType, notSupportWake, devInfo: { isCloudOnline, isOnline, wifiEnableState, isMatter }, } = runtime.config;
27
27
  const supportWifi = hasCapabilityForRuntime(runtime, ProductCommunicationType.WIFI);
28
28
  const supportBle = hasCapabilityForRuntime(runtime, ProductCommunicationType.BLUETOOTH);
29
29
  const supportThread = hasCapabilityForRuntime(runtime, ProductCommunicationType.THREAD);
@@ -38,7 +38,7 @@ export const getDeviceStatusForRuntime = (runtime) => {
38
38
  const isMatterLocal = isOnlineByType(onlineType, 8);
39
39
  const isBleOnline = isOnlineByType(onlineType, 2);
40
40
  const isLocalOnline = !isCloudOnline && isOnlineByType(onlineType, 1);
41
- const hasWirelessAwakeDp = hasDpForRuntime(runtime, dpCodes.wirelessAwake);
41
+ const hasWirelessAwakeDp = !notSupportWake && hasDpForRuntime(runtime, dpCodes.wirelessAwake);
42
42
  const wirelessAwake = getDpValueForRuntime(runtime, dpCodes.wirelessAwake);
43
43
  status.connectEnable = isSupportBleControlForRuntime(runtime) && !isOnline;
44
44
  if (supportWifi) {