react-native-gizwits-sdk-v5 2.1.0-beta → 2.1.1-beta
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/README.md +13 -4
- package/harmony/react_native_gizwits_sdk_v5.har +0 -0
- package/lib/harmony/device.d.ts +5 -4
- package/lib/harmony/device.js +21 -9
- package/lib/harmony/device.js.map +1 -1
- package/lib/harmony/specs/NativeRNGizDeviceManagerModule.d.ts +4 -0
- package/lib/harmony/specs/NativeRNGizDeviceManagerModule.js.map +1 -1
- package/lib/types.d.ts +4 -3
- package/package.json +7 -2
- package/scripts/bundle-harmony-sdk.py +106 -0
- package/scripts/check-harmony-har.js +78 -1
- package/scripts/test-harmony-ble.cjs +83 -0
package/README.md
CHANGED
|
@@ -34,7 +34,7 @@ device.mqttCapability.getDp()
|
|
|
34
34
|
|
|
35
35
|
## BLE Wi-Fi 列表和时间同步(2.1.0-beta)
|
|
36
36
|
|
|
37
|
-
Android / iOS 可以从设备的 BLE 能力获取附近 Wi-Fi,或用手机当前时间独立校准设备时间:
|
|
37
|
+
Android / iOS / HarmonyOS 可以从设备的 BLE 能力获取附近 Wi-Fi,或用手机当前时间独立校准设备时间:
|
|
38
38
|
|
|
39
39
|
```typescript
|
|
40
40
|
const networks = await device.bleCapability.getWiFiList(30)
|
|
@@ -58,8 +58,12 @@ V2 需要固件支持离线时间同步扩展。V5 时间同步成功表示数
|
|
|
58
58
|
协议没有额外的设备确认响应。安全通道由原生 SDK 按设备能力自动协商,
|
|
59
59
|
业务层无需显式启用 ECDH/AES-GCM。历史配网日志主动拉取已废弃,不提供接口。
|
|
60
60
|
|
|
61
|
-
HarmonyOS
|
|
61
|
+
HarmonyOS 同一设备的 Wi-Fi 列表和时间同步共用 BLE 会话,需要依次调用;
|
|
62
|
+
请求尚未完成时启动另一操作会返回 `E_BLE_REQUEST_BUSY`。
|
|
63
|
+
设备的 `bleCapability.profile.support5GConfig`(别名 `supports5GConfig`)和
|
|
64
|
+
`supportsSecureChannel` 表示其广播中的能力,实际使用仍需固件支持。
|
|
62
65
|
本版本依赖 Android SDK `1.4.14`、iOS SDK `~> 2.1.9`。
|
|
66
|
+
HarmonyOS HAR 内置本地构建的四个 SDK 模块,无需先将原生 SDK 发布到 OHPM。
|
|
63
67
|
|
|
64
68
|
## 连接的云服务
|
|
65
69
|
|
|
@@ -126,7 +130,7 @@ import RNGizSDKManagerModule, {
|
|
|
126
130
|
| Wi-Fi 配网及停止配网 | BLE V2/V5 | 支持 | 不支持 |
|
|
127
131
|
| 启动 OTA 升级 | 支持 | 不支持 | 不支持 |
|
|
128
132
|
| 取消 OTA 升级 | 支持 | 不支持 | 不支持 |
|
|
129
|
-
| Wi-Fi 列表、独立时间同步及取消 |
|
|
133
|
+
| Wi-Fi 列表、独立时间同步及取消 | BLE V2/V5 | 不支持 | 不支持 |
|
|
130
134
|
|
|
131
135
|
### HarmonyOS 权限
|
|
132
136
|
|
|
@@ -146,11 +150,16 @@ import RNGizSDKManagerModule, {
|
|
|
146
150
|
|
|
147
151
|
## 更新日志
|
|
148
152
|
|
|
153
|
+
### 2.1.1-beta
|
|
154
|
+
|
|
155
|
+
- HarmonyOS 接入 Wi-Fi 列表、独立时间同步和对应取消接口,补齐 5 GHz 与安全通道能力标记。
|
|
156
|
+
- 内置四个本地原生 SDK HAR,不依赖尚未发布的 OHPM 版本;补充超时、取消和桥接销毁测试。
|
|
157
|
+
|
|
149
158
|
### 2.1.0-beta
|
|
150
159
|
|
|
151
160
|
- 增加 BLE Wi-Fi 列表、独立时间同步及对应取消接口;补齐 TypeScript 类型和设备事件对象上的方法。
|
|
152
161
|
- Android SDK 升级至 1.4.14,iOS SDK 升级至 2.1.9;修复 Android 发布包 Kotlin 顶层扩展索引缺失问题。
|
|
153
|
-
- HarmonyOS
|
|
162
|
+
- Android/iOS 支持新增接口;HarmonyOS 支持在 2.1.1-beta 补齐。
|
|
154
163
|
|
|
155
164
|
### 2.0.0-beta
|
|
156
165
|
|
|
Binary file
|
package/lib/harmony/device.d.ts
CHANGED
|
@@ -9,10 +9,11 @@ export declare class RNGizDeviceManagerModule extends Base {
|
|
|
9
9
|
private ensureNativeListeners;
|
|
10
10
|
sendDp(id: string, type: GizCapability, data: object): Promise<GizResult<GizDeviceData, string>>;
|
|
11
11
|
getDp(id: string, type: GizCapability, attrs?: string[]): Promise<GizResult<GizDeviceData, string>>;
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
private invokeBle;
|
|
13
|
+
getWiFiList(id: string, timeoutSeconds?: number): Promise<GizResult<GizWiFiNetwork[], string>>;
|
|
14
|
+
cancelGetWiFiList(id: string): Promise<GizResult<null, string>>;
|
|
15
|
+
syncTime(id: string, timeoutSeconds?: number): Promise<GizResult<null, string>>;
|
|
16
|
+
cancelSyncTime(id: string): Promise<GizResult<null, string>>;
|
|
16
17
|
getDeviceInfo(id: string, type: GizCapability): Promise<GizResult<GizDeviceInfoProfile, string>>;
|
|
17
18
|
connect(id: string, type: GizCapability): Promise<GizResult<unknown, string>>;
|
|
18
19
|
disConnect(id: string, type: GizCapability): Promise<GizResult<unknown, string>>;
|
package/lib/harmony/device.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { NativeEventEmitter } from 'react-native';
|
|
2
2
|
import Base from '../Base';
|
|
3
|
-
import { invokeNative, parseNativeEvent, unsupported } from './bridge';
|
|
3
|
+
import { failure, invokeNative, parseNativeEvent, unsupported } from './bridge';
|
|
4
4
|
import { DeviceNativeModule } from './native';
|
|
5
5
|
export class RNGizDeviceManagerModule extends Base {
|
|
6
6
|
constructor() {
|
|
@@ -57,17 +57,29 @@ export class RNGizDeviceManagerModule extends Base {
|
|
|
57
57
|
getDp(id, type, attrs) {
|
|
58
58
|
return invokeNative(DeviceNativeModule, 'getDp', { id, type, attrs });
|
|
59
59
|
}
|
|
60
|
-
|
|
61
|
-
|
|
60
|
+
invokeBle(method, id, timeoutSeconds) {
|
|
61
|
+
if (timeoutSeconds !== undefined &&
|
|
62
|
+
(!Number.isFinite(timeoutSeconds) ||
|
|
63
|
+
timeoutSeconds <= 0 ||
|
|
64
|
+
timeoutSeconds > 3600)) {
|
|
65
|
+
return Promise.resolve(failure('E_BLE_INVALID_TIMEOUT', 'timeoutSeconds must be greater than 0 and at most 3600'));
|
|
66
|
+
}
|
|
67
|
+
return invokeNative(DeviceNativeModule, method, {
|
|
68
|
+
id,
|
|
69
|
+
...(timeoutSeconds === undefined ? {} : { timeoutSeconds }),
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
getWiFiList(id, timeoutSeconds = 30) {
|
|
73
|
+
return this.invokeBle('getWiFiList', id, timeoutSeconds);
|
|
62
74
|
}
|
|
63
|
-
cancelGetWiFiList(
|
|
64
|
-
return
|
|
75
|
+
cancelGetWiFiList(id) {
|
|
76
|
+
return this.invokeBle('cancelGetWiFiList', id);
|
|
65
77
|
}
|
|
66
|
-
syncTime(
|
|
67
|
-
return
|
|
78
|
+
syncTime(id, timeoutSeconds = 30) {
|
|
79
|
+
return this.invokeBle('syncTime', id, timeoutSeconds);
|
|
68
80
|
}
|
|
69
|
-
cancelSyncTime(
|
|
70
|
-
return
|
|
81
|
+
cancelSyncTime(id) {
|
|
82
|
+
return this.invokeBle('cancelSyncTime', id);
|
|
71
83
|
}
|
|
72
84
|
getDeviceInfo(id, type) {
|
|
73
85
|
return invokeNative(DeviceNativeModule, 'getDeviceInfo', { id, type });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"device.js","sourceRoot":"","sources":["../../src/harmony/device.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAA;AAEjD,OAAO,IAAI,MAAM,SAAS,CAAA;AAmB1B,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"device.js","sourceRoot":"","sources":["../../src/harmony/device.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,6 +3,10 @@ export type GizNativeCallback = (error: Object | null, result: Object | null) =>
|
|
|
3
3
|
export interface Spec extends TurboModule {
|
|
4
4
|
sendDp(options: Object, callback: GizNativeCallback): void;
|
|
5
5
|
getDp(options: Object, callback: GizNativeCallback): void;
|
|
6
|
+
getWiFiList(options: Object, callback: GizNativeCallback): void;
|
|
7
|
+
cancelGetWiFiList(options: Object, callback: GizNativeCallback): void;
|
|
8
|
+
syncTime(options: Object, callback: GizNativeCallback): void;
|
|
9
|
+
cancelSyncTime(options: Object, callback: GizNativeCallback): void;
|
|
6
10
|
getDeviceInfo(options: Object, callback: GizNativeCallback): void;
|
|
7
11
|
connect(options: Object, callback: GizNativeCallback): void;
|
|
8
12
|
disConnect(options: Object, callback: GizNativeCallback): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NativeRNGizDeviceManagerModule.js","sourceRoot":"","sources":["../../../src/harmony/specs/NativeRNGizDeviceManagerModule.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"NativeRNGizDeviceManagerModule.js","sourceRoot":"","sources":["../../../src/harmony/specs/NativeRNGizDeviceManagerModule.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AAqClD,eAAe,mBAAmB,CAAC,GAAG,CAAO,0BAA0B,CAAC,CAAA"}
|
package/lib/types.d.ts
CHANGED
|
@@ -107,9 +107,10 @@ export interface GizBleProfile extends GizBaseProfile {
|
|
|
107
107
|
blueToothVersion: BlueToothVersion;
|
|
108
108
|
bluetoothVersion?: BlueToothVersion;
|
|
109
109
|
bleModuleVariant?: GizBleModuleVariant;
|
|
110
|
-
/** Android advertisement metadata; the native SDK negotiates security automatically. */
|
|
110
|
+
/** Android/HarmonyOS advertisement metadata; the native SDK negotiates security automatically. */
|
|
111
111
|
supportsSecureChannel?: boolean;
|
|
112
112
|
support5GConfig?: boolean;
|
|
113
|
+
supports5GConfig?: boolean;
|
|
113
114
|
}
|
|
114
115
|
export interface GizMQTTProfile extends GizBaseProfile {
|
|
115
116
|
host: string;
|
|
@@ -127,10 +128,10 @@ export interface GizWiFiNetwork {
|
|
|
127
128
|
}
|
|
128
129
|
export interface GizBleCapability extends GizBaseCapability {
|
|
129
130
|
profile: GizBleProfile;
|
|
130
|
-
/** Android/iOS. Timeout includes connection and authentication; default 30 seconds. */
|
|
131
|
+
/** Android/iOS/HarmonyOS. Timeout includes connection and authentication; default 30 seconds. */
|
|
131
132
|
getWiFiList: (timeoutSeconds?: number) => Promise<GizResult<GizWiFiNetwork[], number | string>>;
|
|
132
133
|
cancelGetWiFiList: () => Promise<GizResult<null, number | string>>;
|
|
133
|
-
/** Android/iOS. V5 success means GATT accepted the write; V2 requires firmware's time extension. */
|
|
134
|
+
/** Android/iOS/HarmonyOS. V5 success means GATT accepted the write; V2 requires firmware's time extension. */
|
|
134
135
|
syncTime: (timeoutSeconds?: number) => Promise<GizResult<null, number | string>>;
|
|
135
136
|
cancelSyncTime: () => Promise<GizResult<null, number | string>>;
|
|
136
137
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-gizwits-sdk-v5",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.1-beta",
|
|
4
4
|
"description": "Gizwits Smart SDK v5 bridge for React Native on Android, iOS and HarmonyOS",
|
|
5
5
|
"homepage": "https://github.com/demchenkoalex/react-native-gizwits-sdk-v5#readme",
|
|
6
6
|
"main": "lib/index",
|
|
@@ -45,7 +45,9 @@
|
|
|
45
45
|
"build:harmony": "bash ./harmony/react_native_gizwits_sdk_v5/build.sh",
|
|
46
46
|
"sync:harmony-version": "node ./scripts/sync-harmony-version.js",
|
|
47
47
|
"version": "npm run sync:harmony-version",
|
|
48
|
-
"check:publish": "node ./scripts/check-publish.js"
|
|
48
|
+
"check:publish": "node ./scripts/check-publish.js",
|
|
49
|
+
"bundle:harmony-sdk": "python3 ./scripts/bundle-harmony-sdk.py",
|
|
50
|
+
"test:harmony-ble": "node --test ./scripts/test-harmony-ble.cjs"
|
|
49
51
|
},
|
|
50
52
|
"devDependencies": {
|
|
51
53
|
"@babel/core": "^7.16.12",
|
|
@@ -87,6 +89,9 @@
|
|
|
87
89
|
"jsx",
|
|
88
90
|
"json",
|
|
89
91
|
"node"
|
|
92
|
+
],
|
|
93
|
+
"roots": [
|
|
94
|
+
"<rootDir>/src"
|
|
90
95
|
]
|
|
91
96
|
}
|
|
92
97
|
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Build a local Gizwits SDK snapshot and vendor all four HARs without publishing."""
|
|
3
|
+
import argparse
|
|
4
|
+
import hashlib
|
|
5
|
+
import io
|
|
6
|
+
import json
|
|
7
|
+
import os
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
import shutil
|
|
10
|
+
import subprocess
|
|
11
|
+
import tarfile
|
|
12
|
+
import tempfile
|
|
13
|
+
|
|
14
|
+
MODULES = ['sdk', 'sdk_bluetooth', 'sdk_lan', 'sdk_mqtt']
|
|
15
|
+
EXCLUDE = {'.git', '.hvigor', '.cxx', '.idea', 'oh_modules', 'node_modules', 'build', '.DS_Store'}
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def main():
|
|
19
|
+
parser = argparse.ArgumentParser(description=__doc__)
|
|
20
|
+
parser.add_argument('--sdk-root', type=Path, required=True)
|
|
21
|
+
args = parser.parse_args()
|
|
22
|
+
source = args.sdk_root.resolve()
|
|
23
|
+
if not (source / 'sdk/src/main/cpp/parser/protocolParser.c').is_file():
|
|
24
|
+
parser.error('Initialize the SDK parser submodule before building')
|
|
25
|
+
repo = Path(__file__).resolve().parents[1]
|
|
26
|
+
module_dir = repo / 'harmony/react_native_gizwits_sdk_v5'
|
|
27
|
+
studio = Path(os.environ.get('DEVECO_STUDIO_HOME', '/Applications/DevEco-Studio.app/Contents'))
|
|
28
|
+
digest = hashlib.sha256()
|
|
29
|
+
for module in MODULES:
|
|
30
|
+
for file in sorted((source / module).rglob('*')):
|
|
31
|
+
relative = file.relative_to(source)
|
|
32
|
+
if not file.is_file() or any(part in EXCLUDE for part in relative.parts):
|
|
33
|
+
continue
|
|
34
|
+
if file.name in {'BuildProfile.ets', 'oh-package-lock.json5'}:
|
|
35
|
+
continue
|
|
36
|
+
digest.update(str(relative).encode())
|
|
37
|
+
digest.update(file.read_bytes())
|
|
38
|
+
snapshot = digest.hexdigest()[:12]
|
|
39
|
+
base = json.loads((source / 'sdk/oh-package.json5').read_text())['version']
|
|
40
|
+
if '-' in base:
|
|
41
|
+
parser.error('Choose a stable base version in the SDK manifest before making a local snapshot')
|
|
42
|
+
work = Path(tempfile.mkdtemp(prefix='gizwits-native-local-'))
|
|
43
|
+
shutil.copytree(source, work, dirs_exist_ok=True, symlinks=True,
|
|
44
|
+
ignore=lambda _dir, names: [n for n in names if n in EXCLUDE])
|
|
45
|
+
profile = json.loads((work / 'build-profile.json5').read_text())
|
|
46
|
+
profile['app'].pop('signingConfigs', None)
|
|
47
|
+
for product in profile['app'].get('products', []):
|
|
48
|
+
product.pop('signingConfig', None)
|
|
49
|
+
(work / 'build-profile.json5').write_text(json.dumps(profile, indent=2) + '\n')
|
|
50
|
+
versions = {}
|
|
51
|
+
for module in MODULES:
|
|
52
|
+
suffix = '' if module == 'sdk' else module.removeprefix('sdk_') + '.'
|
|
53
|
+
version = f'{base}-{suffix}local.{snapshot}'
|
|
54
|
+
versions[module] = version
|
|
55
|
+
manifest_path = work / module / 'oh-package.json5'
|
|
56
|
+
manifest = json.loads(manifest_path.read_text())
|
|
57
|
+
manifest['version'] = version
|
|
58
|
+
if module != 'sdk':
|
|
59
|
+
manifest['dependencies']['@gizwits/smart-sdk'] = versions['sdk']
|
|
60
|
+
manifest_path.write_text(json.dumps(manifest, indent=2) + '\n')
|
|
61
|
+
environment = os.environ.copy()
|
|
62
|
+
environment.update(NODE_HOME=str(studio / 'tools/node'), DEVECO_SDK_HOME=str(studio / 'sdk'),
|
|
63
|
+
JAVA_HOME=str(studio / 'jbr/Contents/Home'))
|
|
64
|
+
subprocess.run([str(studio / 'tools/ohpm/bin/ohpm'), 'install'], cwd=work, env=environment, check=True)
|
|
65
|
+
outputs = {}
|
|
66
|
+
for module in MODULES:
|
|
67
|
+
subprocess.run([str(studio / 'tools/hvigor/bin/hvigorw'), '--mode', 'module', '-p', 'product=default',
|
|
68
|
+
'-p', f'module={module}@default', '-p', 'buildMode=release', 'assembleHar', '--no-daemon'],
|
|
69
|
+
cwd=work, env=environment, check=True)
|
|
70
|
+
outputs[module] = work / module / 'build/default/outputs/default' / f'{module}.har'
|
|
71
|
+
# Each transport carries the exact same core archive, so none of its transitive
|
|
72
|
+
# dependencies can fall back to the older public core. Check clean-consumer
|
|
73
|
+
# resolution and core identity when changing this packaging layout.
|
|
74
|
+
vendored = work / 'vendored'
|
|
75
|
+
vendored.mkdir()
|
|
76
|
+
core = outputs['sdk'].read_bytes()
|
|
77
|
+
(vendored / 'sdk.har').write_bytes(core)
|
|
78
|
+
for module in MODULES[1:]:
|
|
79
|
+
with tarfile.open(outputs[module]) as original, tarfile.open(vendored / f'{module}.har', 'w:gz') as output:
|
|
80
|
+
for member in original.getmembers():
|
|
81
|
+
stream = original.extractfile(member) if member.isfile() else None
|
|
82
|
+
if member.name == 'package/oh-package.json5':
|
|
83
|
+
manifest = json.load(stream)
|
|
84
|
+
manifest['dependencies']['@gizwits/smart-sdk'] = 'file:./vendor/sdk.har'
|
|
85
|
+
data = (json.dumps(manifest, indent=2) + '\n').encode()
|
|
86
|
+
member.size = len(data)
|
|
87
|
+
stream = io.BytesIO(data)
|
|
88
|
+
output.addfile(member, stream)
|
|
89
|
+
member = tarfile.TarInfo('package/vendor/sdk.har')
|
|
90
|
+
member.size = len(core)
|
|
91
|
+
member.mode = 0o644
|
|
92
|
+
output.addfile(member, io.BytesIO(core))
|
|
93
|
+
destination = module_dir / 'libs'
|
|
94
|
+
destination.mkdir(exist_ok=True)
|
|
95
|
+
for module in MODULES:
|
|
96
|
+
shutil.copy2(vendored / f'{module}.har', destination / f'{module}.har')
|
|
97
|
+
metadata = {'baseVersion': base, 'sourceDigest': snapshot, 'modules': {
|
|
98
|
+
module: {'version': versions[module], 'sha256': hashlib.sha256((destination / f'{module}.har').read_bytes()).hexdigest()}
|
|
99
|
+
for module in MODULES
|
|
100
|
+
}}
|
|
101
|
+
(destination / 'sdk-snapshot.json').write_text(json.dumps(metadata, indent=2) + '\n')
|
|
102
|
+
print(f'Local SDK snapshot {snapshot} bundled at {destination}; no registry publication performed.')
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
if __name__ == '__main__':
|
|
106
|
+
main()
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
const fs = require('fs')
|
|
4
4
|
const path = require('path')
|
|
5
|
+
const os = require('os')
|
|
6
|
+
const crypto = require('crypto')
|
|
5
7
|
const { execFileSync } = require('child_process')
|
|
6
8
|
|
|
7
9
|
const repositoryDir = path.resolve(__dirname, '..')
|
|
@@ -48,10 +50,85 @@ if (
|
|
|
48
50
|
) {
|
|
49
51
|
throw new Error('HAR name/version does not match the root npm package')
|
|
50
52
|
}
|
|
53
|
+
const bundledModules = {
|
|
54
|
+
'@gizwits/smart-sdk': 'sdk',
|
|
55
|
+
'@gizwits/smart-sdk-bluetooth': 'sdk_bluetooth',
|
|
56
|
+
'@gizwits/smart-sdk-lan': 'sdk_lan',
|
|
57
|
+
'@gizwits/smart-sdk-mqtt': 'sdk_mqtt',
|
|
58
|
+
}
|
|
51
59
|
for (const [name, version] of Object.entries(manifest.dependencies || {})) {
|
|
52
60
|
if (/^(?:file:|\.{1,2}[/\\]|[/\\]|[A-Za-z]:)/.test(version)) {
|
|
53
|
-
|
|
61
|
+
const module = bundledModules[name]
|
|
62
|
+
if (
|
|
63
|
+
!module ||
|
|
64
|
+
version !== `file:./libs/${module}.har` ||
|
|
65
|
+
!entries.has(`package/libs/${module}.har`)
|
|
66
|
+
) {
|
|
67
|
+
throw new Error(
|
|
68
|
+
`HAR contains an unbundled local dependency: ${name}=${version}`
|
|
69
|
+
)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
const snapshot = JSON.parse(
|
|
74
|
+
execFileSync('tar', ['-xOf', harPath, 'package/libs/sdk-snapshot.json'], {
|
|
75
|
+
encoding: 'utf8',
|
|
76
|
+
})
|
|
77
|
+
)
|
|
78
|
+
const temporary = fs.mkdtempSync(path.join(os.tmpdir(), 'gizwits-har-check-'))
|
|
79
|
+
try {
|
|
80
|
+
let coreBytes
|
|
81
|
+
for (const [name, module] of Object.entries(bundledModules)) {
|
|
82
|
+
if (manifest.dependencies[name] !== `file:./libs/${module}.har`) {
|
|
83
|
+
throw new Error(`HAR must carry the local SDK: ${name}`)
|
|
84
|
+
}
|
|
85
|
+
const bytes = execFileSync(
|
|
86
|
+
'tar',
|
|
87
|
+
['-xOf', harPath, `package/libs/${module}.har`],
|
|
88
|
+
{ maxBuffer: 32 * 1024 * 1024 }
|
|
89
|
+
)
|
|
90
|
+
const hash = crypto.createHash('sha256').update(bytes).digest('hex')
|
|
91
|
+
if (hash !== snapshot.modules[module].sha256)
|
|
92
|
+
throw new Error(`SDK snapshot hash mismatch: ${module}`)
|
|
93
|
+
const nativePath = path.join(temporary, `${module}.har`)
|
|
94
|
+
fs.writeFileSync(nativePath, bytes)
|
|
95
|
+
const native = JSON.parse(
|
|
96
|
+
execFileSync('tar', ['-xOf', nativePath, 'package/oh-package.json5'], {
|
|
97
|
+
encoding: 'utf8',
|
|
98
|
+
})
|
|
99
|
+
)
|
|
100
|
+
if (
|
|
101
|
+
native.name !== name ||
|
|
102
|
+
native.version !== snapshot.modules[module].version
|
|
103
|
+
) {
|
|
104
|
+
throw new Error(`SDK snapshot metadata mismatch: ${module}`)
|
|
105
|
+
}
|
|
106
|
+
if (module === 'sdk') {
|
|
107
|
+
coreBytes = bytes
|
|
108
|
+
const nativeEntries = execFileSync('tar', ['-tf', nativePath], {
|
|
109
|
+
encoding: 'utf8',
|
|
110
|
+
}).split('\n')
|
|
111
|
+
for (const abi of ['arm64-v8a', 'x86_64']) {
|
|
112
|
+
if (!nativeEntries.includes(`package/libs/${abi}/libgiz_parser.so`))
|
|
113
|
+
throw new Error(`Missing parser for ${abi}`)
|
|
114
|
+
}
|
|
115
|
+
} else {
|
|
116
|
+
if (
|
|
117
|
+
native.dependencies['@gizwits/smart-sdk'] !== 'file:./vendor/sdk.har'
|
|
118
|
+
) {
|
|
119
|
+
throw new Error(`${module} still depends on a registry core`)
|
|
120
|
+
}
|
|
121
|
+
const nested = execFileSync(
|
|
122
|
+
'tar',
|
|
123
|
+
['-xOf', nativePath, 'package/vendor/sdk.har'],
|
|
124
|
+
{ maxBuffer: 32 * 1024 * 1024 }
|
|
125
|
+
)
|
|
126
|
+
if (!nested.equals(coreBytes))
|
|
127
|
+
throw new Error(`${module} contains a different core`)
|
|
128
|
+
}
|
|
54
129
|
}
|
|
130
|
+
} finally {
|
|
131
|
+
fs.rmSync(temporary, { recursive: true, force: true })
|
|
55
132
|
}
|
|
56
133
|
if ([...entries].some((entry) => entry.startsWith('package/AppScope/'))) {
|
|
57
134
|
throw new Error('HAR must not contain the local build project AppScope')
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
const test = require('node:test')
|
|
2
|
+
const assert = require('node:assert/strict')
|
|
3
|
+
const fs = require('node:fs')
|
|
4
|
+
const path = require('node:path')
|
|
5
|
+
const vm = require('node:vm')
|
|
6
|
+
const ts = require('typescript')
|
|
7
|
+
const root = path.join(__dirname, '../harmony/react_native_gizwits_sdk_v5/src/main/ets')
|
|
8
|
+
const registered = new Map()
|
|
9
|
+
const core = { GizSDKManager: { getRegisteredDevice: id => registered.get(id) } }
|
|
10
|
+
const cache = new Map()
|
|
11
|
+
function load(name) {
|
|
12
|
+
if (cache.has(name)) return cache.get(name)
|
|
13
|
+
const source = fs.readFileSync(path.join(root, name + '.ets'), 'utf8')
|
|
14
|
+
const compiled = ts.transpileModule(source, { compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020 } })
|
|
15
|
+
const sandbox = { exports: {}, Error, require: dep => {
|
|
16
|
+
if (dep === '@gizwits/smart-sdk') return core
|
|
17
|
+
if (dep === '@rnoh/react-native-openharmony/ets') return { EtsUITurboModule: class { __onDestroy__() {} } }
|
|
18
|
+
if (dep === './generated/ts') return { TM: { RNGizDeviceManagerModule: { NAME: 'RNGizDeviceManagerModule' } } }
|
|
19
|
+
if (dep === './GizDTOMapper') return {}
|
|
20
|
+
return load(dep.replace('./', ''))
|
|
21
|
+
} }
|
|
22
|
+
vm.runInNewContext(compiled.outputText, sandbox)
|
|
23
|
+
cache.set(name, sandbox.exports)
|
|
24
|
+
return sandbox.exports
|
|
25
|
+
}
|
|
26
|
+
const { GizBleRequestRegistry: Registry } = load('GizBleRequestRegistry')
|
|
27
|
+
const { RNGizDeviceManagerModule: Module } = load('RNGizDeviceManagerModule')
|
|
28
|
+
const invoke = (module, name, payload) => new Promise(resolve => module[name](payload, (error, result) => resolve(error || result)))
|
|
29
|
+
const tick = () => new Promise(resolve => setTimeout(resolve, 0))
|
|
30
|
+
test('native bridge converts seconds to milliseconds and preserves signed RSSI/UTF-8/duplicates', async () => {
|
|
31
|
+
const module = new Module(), calls = []
|
|
32
|
+
const networks = [{ ssid: '家', signalStrength: -50 }, { ssid: '家', signalStrength: -80 }]
|
|
33
|
+
const device = { bleCapability: { getWiFiList: async (owner, timeout) => { calls.push([owner, timeout]); return networks },
|
|
34
|
+
syncTime: async (owner, timeout) => { calls.push([owner, timeout]) } } }
|
|
35
|
+
registered.set('a', device)
|
|
36
|
+
assert.deepEqual(JSON.parse(JSON.stringify(await invoke(module, 'getWiFiList', { id: 'a', timeoutSeconds: 0.25 }))).data, networks)
|
|
37
|
+
assert.equal((await invoke(module, 'syncTime', { id: 'a' })).data, null)
|
|
38
|
+
assert.equal(calls[0][0], device); assert.equal(calls[0][1], 250); assert.equal(calls[1][1], 30000)
|
|
39
|
+
})
|
|
40
|
+
test('native calls also reject invalid timeouts and missing devices', async () => {
|
|
41
|
+
const module = new Module()
|
|
42
|
+
for (const timeoutSeconds of [0, -1, null, '30', Infinity, NaN, 3601]) {
|
|
43
|
+
assert.equal((await invoke(module, 'getWiFiList', { id: 'missing', timeoutSeconds })).error, 'E_BLE_INVALID_TIMEOUT')
|
|
44
|
+
}
|
|
45
|
+
assert.equal((await invoke(module, 'syncTime', { id: 'missing' })).success, false)
|
|
46
|
+
})
|
|
47
|
+
test('native cancellation targets its operation and settles old requests exactly once', async () => {
|
|
48
|
+
const module = new Module(); let release; const cancelled = []
|
|
49
|
+
registered.set('cancel', { bleCapability: {
|
|
50
|
+
getWiFiList: () => new Promise(resolve => { release = resolve }),
|
|
51
|
+
cancelWiFiList: () => cancelled.push('wifi'),
|
|
52
|
+
cancelSyncTime: () => cancelled.push('time'),
|
|
53
|
+
} })
|
|
54
|
+
const pending = invoke(module, 'getWiFiList', { id: 'cancel' })
|
|
55
|
+
assert.equal((await invoke(module, 'cancelSyncTime', { id: 'cancel' })).success, true)
|
|
56
|
+
assert.deepEqual(cancelled, [])
|
|
57
|
+
assert.equal((await invoke(module, 'cancelGetWiFiList', { id: 'cancel' })).data, null)
|
|
58
|
+
assert.equal((await pending).error, 'E_BLE_REQUEST_CANCELLED')
|
|
59
|
+
assert.deepEqual(cancelled, ['wifi']); release([]); await tick()
|
|
60
|
+
})
|
|
61
|
+
test('request registry rejects duplicates, isolates devices, and ignores stale replies', async () => {
|
|
62
|
+
const registry = new Registry(); let oldRelease, newRelease; let cancels = 0
|
|
63
|
+
const old = registry.run('wifi:a', () => { cancels++ }, () => new Promise(resolve => { oldRelease = resolve }))
|
|
64
|
+
assert.equal(JSON.parse(await registry.run('wifi:a', () => {}, async () => assert.fail())).error, 'E_BLE_REQUEST_BUSY')
|
|
65
|
+
assert.equal(await registry.run('wifi:b', () => {}, async () => 'other'), 'other')
|
|
66
|
+
registry.cancel('wifi:a'); assert.equal(JSON.parse(await old).error, 'E_BLE_REQUEST_CANCELLED')
|
|
67
|
+
const next = registry.run('wifi:a', () => {}, () => new Promise(resolve => { newRelease = resolve }))
|
|
68
|
+
oldRelease('stale'); await tick(); newRelease('fresh'); assert.equal(await next, 'fresh'); assert.equal(cancels, 1)
|
|
69
|
+
})
|
|
70
|
+
test('bridge teardown cancels native requests and blocks new work', async () => {
|
|
71
|
+
const module = new Module(); let cancelled = 0
|
|
72
|
+
registered.set('close', { bleCapability: { syncTime: () => new Promise(() => {}), cancelSyncTime: () => { cancelled++ } } })
|
|
73
|
+
const pending = invoke(module, 'syncTime', { id: 'close' }); module.__onDestroy__()
|
|
74
|
+
assert.equal((await pending).error, 'E_BLE_REQUEST_CANCELLED'); assert.equal(cancelled, 1)
|
|
75
|
+
assert.equal((await invoke(module, 'syncTime', { id: 'close' })).error, 'E_BLE_REQUEST_CANCELLED')
|
|
76
|
+
})
|
|
77
|
+
test('native timeout errors stay distinct from successful empty Wi-Fi lists', async () => {
|
|
78
|
+
const module = new Module()
|
|
79
|
+
registered.set('failure', { bleCapability: { getWiFiList: async () => { throw new Error('BLE operation timed out') } } })
|
|
80
|
+
assert.equal((await invoke(module, 'getWiFiList', { id: 'failure' })).error, 'E_BLE_REQUEST_TIMEOUT')
|
|
81
|
+
registered.set('empty', { bleCapability: { getWiFiList: async () => [] } })
|
|
82
|
+
assert.equal((await invoke(module, 'getWiFiList', { id: 'empty' })).data.length, 0)
|
|
83
|
+
})
|