react-native-gizwits-sdk-v5 2.2.0 → 2.2.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-gizwits-sdk-v5",
3
- "version": "2.2.0",
3
+ "version": "2.2.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",
@@ -47,7 +47,8 @@
47
47
  "version": "npm run sync:harmony-version",
48
48
  "check:publish": "node ./scripts/check-publish.js",
49
49
  "bundle:harmony-sdk": "python3 ./scripts/bundle-harmony-sdk.py",
50
- "test:harmony-ble": "node --test ./scripts/test-harmony-ble.cjs"
50
+ "test:harmony-ble": "node --test ./scripts/test-harmony-ble.cjs",
51
+ "test:harmony-device-list": "node --test scripts/test-harmony-device-list.cjs"
51
52
  },
52
53
  "devDependencies": {
53
54
  "@babel/core": "^7.16.12",
@@ -0,0 +1,62 @@
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('/Applications/DevEco-Studio.app/Contents/tools/hvigor/hvigor/node_modules/typescript');
7
+ const root = process.env.BRIDGE_SOURCE_ROOT || path.resolve(__dirname, '../harmony/react_native_gizwits_sdk_v5/src/main/ets');
8
+ class State {
9
+ constructor(value){this.value=value;this.listeners=new Set();}
10
+ getValue(){return this.value;}
11
+ setValue(value){this.value=value;this.listeners.forEach(fn=>fn(value));}
12
+ subscribe(fn, initial=true){this.listeners.add(fn);if(initial)fn(this.value);return()=>this.listeners.delete(fn);}
13
+ }
14
+ function setup(){
15
+ const devices=[],events=[];const state=new State(devices), advertisements=new Map(), profiles=new Map();
16
+ const core={GizCapacityType:{BLE:'BLE',LAN:'LAN',MQTT:'MQTT'},GizLog:{logger:{w(){}}},
17
+ GizDeviceManager:{subscribeDeviceList:()=>state,getRegisteredDevices:()=>devices},
18
+ GizSDKManager:{getUserManager:()=>({subscribeBoundDeviceList:()=>new State([])})}};
19
+ const ble={GizAuthenticationMethod:{INDEPENDENT:1},GizBleModuleVariant:{CHINA_MOBILE_AIJIA:1},GizBluetoothType:{MESH:1,BEACON:2,VOICE:3},GizBluetoothVersion:{BLE4:1,BLE50:2},GizBluetoothManager:{getAdvertisement:id=>advertisements.get(id)}};
20
+ const lan={GizLanManager:{getProfile:id=>profiles.get(id)}};
21
+ const deps={'@gizwits/smart-sdk':core,'@gizwits/smart-sdk-bluetooth':ble,'@gizwits/smart-sdk-lan':lan,'@gizwits/smart-sdk-mqtt':{GizMqttManager:{subscribeBindEvent:()=>new State(undefined)}}};
22
+ function load(name){const code=ts.transpileModule(fs.readFileSync(path.join(root,name+'.ets'),'utf8'),{compilerOptions:{module:ts.ModuleKind.CommonJS,target:ts.ScriptTarget.ES2020}}).outputText;const s={exports:{},require:n=>{if(!(n in deps))throw Error(n);return deps[n];}};vm.runInNewContext(code,s);return s.exports;}
23
+ deps['./GizDTOMapper']=load('GizDTOMapper');
24
+ const Bridge=load('GizBridgeCoordinator').GizBridgeCoordinator;
25
+ function add(id){
26
+ const cap=()=>{const status=new State(1),login=new State(false);return{getStatus:()=>status.getValue(),getIsLogin:()=>login.getValue(),isActive:()=>true,subscribeStatus:()=>status,subscribeIsLogin:()=>login};};
27
+ const d={id,mac:id,productKey:'pk',name:'test',did:'did-'+id,bound:new State(true),raw:new State(undefined),data:new State(undefined),getName(){return this.name;},getRemark:()=>'',subscribeBoundState(){return this.bound;},subscribeDeviceId(){return new State(this.did);},subscribeDataPointEvents(){return this.data;},subscribeBleAdvertisement(){return this.raw;},bleCapability:cap(),lanCapability:cap(),mqttCapability:cap()};
28
+ d.getCapability=t=>d[t.toLowerCase()+'Capability'];Object.defineProperty(d,'bleAdvertisement',{get:()=>d.raw.getValue()});
29
+ devices.push(d);advertisements.set(id,{platformDeviceId:id,deviceName:'test',rssi:-50,protocolVersion:2,configured:true,requiresAuthentication:false,supportsOTA:true,supports5GConfig:false,supportsSecureTransport:false});profiles.set(id,{address:'192.0.2.1',port:12416,lastSeenAt:1000,observedSsid:'test',observedBssid:'test',observedNetworkAddress:0,observedNetmask:0,observedBroadcastAddress:'192.0.2.255'});return d;
30
+ }
31
+ const emit=(name,payload)=>events.push({name,data:JSON.parse(payload)});
32
+ return{devices,events,advertisements,profiles,Bridge,add,start:()=>Bridge.initialize(emit),notify:()=>state.setValue(devices),count:name=>events.filter(e=>e.name===name).length};
33
+ }
34
+ test('duplicate, reordered, timestamp/RSSI-only lists do not flood RN; payload retains live metadata',()=>{
35
+ const h=setup();for(let i=0;i<42;i++)h.add('d'+i);h.start();
36
+ for(let i=0;i<100;i++){h.profiles.get('d0').lastSeenAt++;h.advertisements.get('d0').rssi--;h.devices.reverse();h.notify();}
37
+ assert.equal(h.count('DeviceListListener'),1);
38
+ h.devices[0].name='renamed';h.notify();assert.equal(h.count('DeviceListListener'),2);
39
+ const list=h.events.filter(e=>e.name==='DeviceListListener').at(-1).data;
40
+ assert.equal(list.find(d=>d.id==='d0').lanCapability.profile.lastSeenAt,1100);
41
+ assert.equal(list.find(d=>d.id==='d0').bleCapability.profile.RSSI,-150);
42
+ h.Bridge.shutdown();
43
+ });
44
+ test('membership, IP, DID and binding changes publish; removed device subscriptions are cleaned',()=>{
45
+ const h=setup(),d=h.add('d');h.start();
46
+ const check=change=>{const n=h.count('DeviceListListener');change();h.notify();assert.equal(h.count('DeviceListListener'),n+1);};
47
+ check(()=>h.profiles.get('d').address='192.0.2.2');check(()=>d.did='new');check(()=>d.bound.setValue(false));
48
+ check(()=>h.add('other'));check(()=>h.devices.splice(0,1));
49
+ const states=h.count('DeviceStateListener');d.bleCapability.subscribeStatus().setValue(2);assert.equal(h.count('DeviceStateListener'),states);
50
+ h.Bridge.shutdown();h.start();assert.equal(h.count('DeviceListListener'),7);h.Bridge.shutdown();
51
+ });
52
+ test('real state, data and raw advertisement events keep separate delivery channels',()=>{
53
+ const h=setup(),d=h.add('d');h.start();const count=h.count('DeviceListListener');
54
+ d.bleCapability.subscribeStatus().setValue(2);assert.equal(h.events.at(-1).name,'DeviceStateListener');
55
+ d.data.setValue({source:'BLE',serialNumber:1,commandCode:1,data:new Map(),alerts:new Map(),faults:new Map(),binary:'0102'});
56
+ assert.equal(h.events.at(-1).name,'DeviceDataListener');
57
+ d.raw.setValue({rawHex:'aa',receivedAt:1000,source:'harmonyos-scan-result'});assert.equal(h.events.at(-1).name,'DeviceBleAdvertisementListener');
58
+ // A real capability transition can still appear in a subsequent SDK list.
59
+ h.notify();const afterState=h.count('DeviceListListener');assert.equal(afterState,count+1);
60
+ d.raw.setValue({rawHex:'bb',receivedAt:1001,source:'harmonyos-scan-result'});h.notify();
61
+ assert.equal(h.count('DeviceListListener'),afterState);assert.equal(h.count('DeviceBleAdvertisementListener'),2);h.Bridge.shutdown();
62
+ });