@eohjsc/react-native-smart-city 0.7.26 → 0.7.30

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 (74) hide show
  1. package/index.js +2 -0
  2. package/package.json +2 -1
  3. package/src/commons/Dashboard/MyDashboardDevice/__test__/index.test.js +68 -0
  4. package/src/commons/Dashboard/MyDashboardDevice/index.js +46 -11
  5. package/src/commons/Dashboard/MyUnit/__test__/MyUnit.test.js +43 -11
  6. package/src/commons/Dashboard/MyUnit/index.js +40 -32
  7. package/src/commons/ModalAlert/index.js +51 -0
  8. package/src/commons/ModalAlert/styles.js +54 -0
  9. package/src/commons/SubUnit/ShortDetail.js +20 -4
  10. package/src/commons/SubUnit/__test__/ShortDetail.test.js +46 -1
  11. package/src/configs/API.js +6 -0
  12. package/src/configs/AccessibilityLabel.js +1 -0
  13. package/src/configs/Constants.js +7 -0
  14. package/src/configs/SCConfig.js +6 -0
  15. package/src/context/SCContext.tsx +12 -1
  16. package/src/context/SCStore.ts +14 -0
  17. package/src/context/actionType.ts +10 -0
  18. package/src/context/mockStore.ts +30 -1
  19. package/src/context/reducer.ts +35 -0
  20. package/src/hooks/IoT/useRemoteControl.js +4 -1
  21. package/src/hooks/IoT/useWatchSharedChips.js +130 -0
  22. package/src/hooks/Review/__test__/useInAppReview.test.js +99 -0
  23. package/src/hooks/Review/useInAppReview.js +70 -0
  24. package/src/hooks/useMqtt.js +78 -27
  25. package/src/iot/Monitor.js +149 -26
  26. package/src/iot/UpdateStates.js +60 -0
  27. package/src/iot/mqtt.js +177 -22
  28. package/src/navigations/UnitStack.js +16 -0
  29. package/src/screens/ActivityLog/FilterPopup.js +4 -79
  30. package/src/screens/ActivityLog/ItemLog.js +1 -0
  31. package/src/screens/ActivityLog/__test__/FilterPopup.test.js +2 -6
  32. package/src/screens/ActivityLog/__test__/index.test.js +51 -29
  33. package/src/screens/ActivityLog/index.js +0 -1
  34. package/src/screens/ActivityLog/styles/filterPopupStyles.js +5 -2
  35. package/src/screens/AddNewGateway/RenameNewDevices.js +5 -0
  36. package/src/screens/AddNewGateway/__test__/RenameNewDevices.test.js +18 -0
  37. package/src/screens/Automate/AddNewAction/ReceiverSelect.js +208 -0
  38. package/src/screens/Automate/AddNewAction/SetupScriptEmail.js +1 -1
  39. package/src/screens/Automate/AddNewAction/SetupScriptNotify.js +18 -28
  40. package/src/screens/Automate/AddNewAction/SetupScriptReceiverEmail.js +22 -129
  41. package/src/screens/Automate/AddNewAction/SetupScriptReceiverNotify.js +59 -0
  42. package/src/screens/Automate/AddNewAction/SetupScriptReceiverSms.js +22 -129
  43. package/src/screens/Automate/AddNewAction/SetupScriptSms.js +1 -1
  44. package/src/screens/Automate/AddNewAction/Styles/{SetupScriptReceiverEmailStyles.js → ReceiverSelectStyles.js} +18 -1
  45. package/src/screens/Automate/AddNewAction/__test__/SetupScriptNotify.test.js +16 -33
  46. package/src/screens/Automate/AddNewAction/__test__/SetupScriptReceiverEmail.test.js +10 -8
  47. package/src/screens/Automate/AddNewAction/__test__/SetupScriptReceiverNotify.test.js +217 -0
  48. package/src/screens/Automate/AddNewAction/__test__/SetupScriptReceiverSms.test.js +10 -8
  49. package/src/screens/Automate/Components/InputName.js +5 -1
  50. package/src/screens/Automate/OneTap/__test__/AddNewOneTap.test.js +18 -0
  51. package/src/screens/Automate/ScriptDetail/index.js +6 -6
  52. package/src/screens/CreatePassword/__test__/index.test.js +133 -0
  53. package/src/screens/CreatePassword/index.js +134 -0
  54. package/src/screens/CreatePassword/styles.js +45 -0
  55. package/src/screens/Device/__test__/DeviceDetail-3rdparty.test.js +447 -0
  56. package/src/screens/Device/__test__/DeviceDetail-arduino.test.js +344 -0
  57. package/src/screens/Device/__test__/{mqttDetail.test.js → DeviceDetail-modbus.test.js} +287 -320
  58. package/src/screens/Device/__test__/DeviceDetail-zigbee.test.js +451 -0
  59. package/src/screens/Device/__test__/DeviceDetail.test.js +502 -0
  60. package/src/screens/Device/__test__/detail.test.js +61 -3
  61. package/src/screens/Device/__test__/sensorDisplayItem.test.js +28 -3
  62. package/src/screens/Device/components/SensorDisplayItem.js +16 -14
  63. package/src/screens/Device/detail.js +14 -6
  64. package/src/screens/Device/hooks/useDeviceWatchConfigControl.js +3 -2
  65. package/src/screens/Device/styles.js +0 -5
  66. package/src/screens/EnterPassword/__test__/EnterPassword.test.js +76 -1
  67. package/src/screens/EnterPassword/index.js +34 -4
  68. package/src/screens/EnterPassword/styles.js +1 -1
  69. package/src/utils/FactoryGateway.js +597 -0
  70. package/src/utils/I18n/translations/en.js +10 -0
  71. package/src/utils/I18n/translations/vi.js +10 -0
  72. package/src/utils/Route/index.js +3 -1
  73. package/src/utils/Validation.js +5 -0
  74. package/src/utils/store.js +5 -0
@@ -1,6 +1,7 @@
1
1
  import { NavigationContext } from '@react-navigation/native';
2
2
  import AsyncStorage from '@react-native-async-storage/async-storage';
3
3
  import MockAdapter from 'axios-mock-adapter';
4
+ import moment from 'moment';
4
5
  import mqtt from 'precompiled-mqtt/dist/mqtt.browser';
5
6
  import React from 'react';
6
7
  import { Alert } from 'react-native';
@@ -10,7 +11,8 @@ import QualityIndicatorItem from '../../../commons/Device/WaterQualitySensor/Qua
10
11
  import { API } from '../../../configs';
11
12
  import { SCProvider } from '../../../context';
12
13
  import { mockSCStore } from '../../../context/mockStore';
13
- import { watchMultiConfigs } from '../../../iot/Monitor';
14
+ import { mqttClientsPool } from '../../../hooks/useMqtt';
15
+ import { unwatchMultiDataChips, watchMultiConfigs } from '../../../iot/Monitor';
14
16
  import { setConfigGlobalState } from '../../../iot/states';
15
17
  import api from '../../../utils/Apis/axios';
16
18
  import {
@@ -25,6 +27,7 @@ jest.mock('../../../iot/Monitor', () => {
25
27
  return {
26
28
  ...jest.requireActual('../../../iot/Monitor'),
27
29
  watchMultiConfigs: jest.fn(),
30
+ unwatchMultiDataChips: jest.fn(),
28
31
  };
29
32
  });
30
33
 
@@ -107,96 +110,14 @@ describe('test DeviceDetail', () => {
107
110
  jest.useFakeTimers();
108
111
  mock.reset();
109
112
  watchMultiConfigs.mockClear();
113
+ unwatchMultiDataChips.mockClear();
110
114
  AsyncStorage.clear();
111
- setConfigGlobalState('configValues', {});
112
- gatewayData = JSON.parse(JSON.stringify(gatewayDataFactory));
113
- });
114
-
115
- it('should render device detail, connect will call subscribe', async () => {
116
- mock.onGet(API.CHIP.JSON_CONFIGURATION).reply(200, [gatewayData]);
117
- const client = mqtt.connect();
118
- await act(async () => {
119
- await create(
120
- wrapComponent(store, account, {
121
- ...route,
122
- params: { ...route.params },
123
- })
124
- );
125
- });
126
- await act(async () => {
127
- client.trigger('connect');
128
- });
129
-
130
- expect(client.subscribe).toHaveBeenCalledWith(
131
- `eoh/chip/${gatewayData.code}/#`
132
- );
133
- });
134
-
135
- it('should render device detail, mqtt_server will not call mqtt connect', async () => {
136
- gatewayData.mqtt_server = null;
137
- mock.onGet(API.CHIP.JSON_CONFIGURATION).reply(200, [gatewayData]);
138
- const mockMqttConnect = jest.spyOn(mqtt, 'connect');
139
- await act(async () => {
140
- await create(
141
- wrapComponent(store, account, {
142
- ...route,
143
- params: { ...route.params },
144
- })
145
- );
146
- });
147
- expect(mockMqttConnect).not.toHaveBeenCalled();
148
- });
149
-
150
- it('should render device detail, allow_frontend_connect is false will not call mqtt connect', async () => {
151
- gatewayData.mqtt_server = {
152
- host: 'example.cloudmqtt.com',
153
- allow_frontend_connect: false,
154
- };
155
-
156
- mock.onGet(API.CHIP.JSON_CONFIGURATION).reply(200, [gatewayData]);
157
- const mockMqttConnect = jest.spyOn(mqtt, 'connect');
158
-
159
- await act(async () => {
160
- await create(
161
- wrapComponent(store, account, {
162
- ...route,
163
- params: { ...route.params },
164
- })
165
- );
166
- });
167
- expect(mockMqttConnect).not.toHaveBeenCalled();
168
- });
169
-
170
- it('should render device detail, call mqtt connect', async () => {
171
- mock.onGet(API.CHIP.JSON_CONFIGURATION).reply(200, [gatewayData]);
172
- const mockMqttConnect = jest.spyOn(mqtt, 'connect');
173
- await act(async () => {
174
- await create(
175
- wrapComponent(store, account, {
176
- ...route,
177
- params: { ...route.params },
178
- })
179
- );
180
- });
181
- expect(mockMqttConnect).toHaveBeenCalledTimes(1);
182
- });
183
-
184
- it('should render device detail, unmount will call mqtt end', async () => {
185
- mock.onGet(API.CHIP.JSON_CONFIGURATION).reply(200, [gatewayData]);
186
- await act(async () => {
187
- tree = await create(
188
- wrapComponent(store, account, {
189
- ...route,
190
- params: { ...route.params, unitId: 1 },
191
- })
192
- );
193
- });
194
-
195
- const client = mqtt.connect();
196
- await act(async () => {
197
- tree.unmount();
115
+ mqttClientsPool.clear();
116
+ act(() => {
117
+ setConfigGlobalState('configValues', {});
198
118
  });
199
- expect(client.end).toHaveBeenCalled();
119
+ gatewayData = JSON.parse(JSON.stringify(gatewayDataFactory));
120
+ mock.onGet(API.CHIP.SHARED_CONFIGURATION).reply(200, []);
200
121
  });
201
122
 
202
123
  const _receiveDataOnDeviceDetail = async (widgetConfigs, topic, message) => {
@@ -251,38 +172,73 @@ describe('test DeviceDetail', () => {
251
172
  return valueBox;
252
173
  };
253
174
 
254
- it('should render device detail, config use mqtt will not call watch config', async () => {
255
- mock.onGet(API.CHIP.JSON_CONFIGURATION).reply(200, [gatewayData]);
256
- mock.onGet(API.DEVICE.DISPLAY(1)).reply(200, [
257
- {
258
- id: 0,
259
- order: 0,
260
- template: 'value',
261
- type: 'value',
262
- configuration: {
263
- template: 'simple_list',
264
- configs: [
265
- {
266
- id: 128282, // mqtt config
267
- },
268
- ],
269
- },
270
- },
271
- ]);
272
- expect(watchMultiConfigs).not.toHaveBeenCalled();
273
- });
274
-
275
175
  // MODBUS
276
- const testModbus = async (data, expect1, expect2) => {
176
+ const testModbus = async (data, expect1, expect2, extra = {}) => {
277
177
  const valueBoxs = await _receiveDataOnDeviceDetail(
278
178
  [{ id: 128323 }, { id: 128324 }],
279
179
  `eoh/chip/${gatewayData.code}/data`,
280
- { data }
180
+ { data, ...extra }
281
181
  );
282
182
  expect(valueBoxs[0].props.value).toEqual(expect1);
283
183
  expect(valueBoxs[1].props.value).toEqual(expect2);
284
184
  };
285
185
 
186
+ it('should render device detail, modbus call updateGlobalValue with past last_updated', async () => {
187
+ act(() => {
188
+ setConfigGlobalState('configValues', {
189
+ 128323: { value: 0, last_updated: moment(1672531200000) },
190
+ 128324: { value: 0, last_updated: moment(1672531200000) },
191
+ });
192
+ });
193
+ await testModbus('00010002', 0, 0, { time: 1672531199 });
194
+ });
195
+
196
+ it('should render device detail, modbus call updateGlobalValue with future last_updated', async () => {
197
+ act(() => {
198
+ setConfigGlobalState('configValues', {
199
+ 128323: { value: 0, last_updated: moment(1672531200000) },
200
+ 128324: { value: 0, last_updated: moment(1672531200000) },
201
+ });
202
+ });
203
+ await testModbus('00010002', 0.1, 0.2, { time: 1672531201 });
204
+ });
205
+
206
+ it('should render device detail, modbus with edge past last_updated', async () => {
207
+ act(() => {
208
+ setConfigGlobalState('configValues', {
209
+ 128323: {
210
+ value: 0,
211
+ last_updated: moment(1672531200123),
212
+ last_updated_micro: 456,
213
+ },
214
+ 128324: {
215
+ value: 0,
216
+ last_updated: moment(1672531200123),
217
+ last_updated_micro: 456,
218
+ },
219
+ });
220
+ });
221
+ await testModbus('00010002', 0, 0, { time: 1672531200.123455 });
222
+ });
223
+
224
+ it('should render device detail, modbus with edge future last_updated', async () => {
225
+ act(() => {
226
+ setConfigGlobalState('configValues', {
227
+ 128323: {
228
+ value: 0,
229
+ last_updated: moment(1672531200123),
230
+ last_updated_micro: 456,
231
+ },
232
+ 128324: {
233
+ value: 0,
234
+ last_updated: moment(1672531200123),
235
+ last_updated_micro: 456,
236
+ },
237
+ });
238
+ });
239
+ await testModbus('00010002', 0.1, 0.2, { time: 1672531200.123457 });
240
+ });
241
+
286
242
  it('should render device detail, modbus not call updateGlobalValue, configs is empty', async () => {
287
243
  gatewayData.sensors = [{ id: configDataFactory.sensor, configs: [] }];
288
244
  await testModbus('00010002', '--', '--');
@@ -544,277 +500,288 @@ describe('test DeviceDetail', () => {
544
500
  await testModbus('00012', 0.1, '--');
545
501
  });
546
502
 
547
- // ARDUINO PIN
548
- const testArduinoPin = async (url, data, expect1, expect2) => {
549
- const valueBoxs = await _receiveDataOnDeviceDetail(
550
- [{ id: 128282 }, { id: 128324 }],
551
- url,
552
- data
553
- );
554
- expect(valueBoxs[0].props.value).toEqual(expect1);
555
- expect(valueBoxs[1].props.value).toEqual(expect2);
503
+ const dataConverterWrongData64 = async (transformer) => {
504
+ gatewayData.mqtt_server.is_wss = false;
505
+ gatewayData.modbus_gateway.sensors[0].configs[1].transformer = transformer;
506
+ gatewayData.modbus_gateway.sensors[0].configs[1].len = 4;
507
+ gatewayData.modbus_gateway.sensors[0].configs[1].len2 = 4;
508
+
509
+ await testModbus('0001P123456712345678', 0.1, '--');
556
510
  };
557
511
 
558
- it('should render device detail, arduino pin call updateGlobalValue', async () => {
559
- await testArduinoPin('config/128282/value/', { v: 10 }, 10, '--');
560
- });
512
+ const dataConverterUint64 = async (transformer, data) => {
513
+ gatewayData.modbus_gateway.sensors[0].configs[1].transformer = transformer;
514
+ gatewayData.modbus_gateway.sensors[0].configs[1].len = 4;
515
+ gatewayData.modbus_gateway.sensors[0].configs[1].len2 = 4;
561
516
 
562
- it('should render device detail, arduino pin call updateGlobalValue, filter zero', async () => {
563
- gatewayData.sensors[0].configs[0].active_filter = 'zero';
564
- await testArduinoPin('config/128282/value/', { v: 0 }, '--', '--');
565
- });
517
+ await testModbus(`0001${data}`, 0.1, 122454561422327.6);
518
+ };
566
519
 
567
- it('should render device detail, arduino pin call updateGlobalValue, filter in range', async () => {
568
- gatewayData.sensors[0].configs[0].active_filter = 'range';
569
- gatewayData.sensors[0].configs[0].high_level = 11;
570
- await testArduinoPin('config/128282/value/', { v: 10 }, 10, '--');
520
+ test('should render device detail, modbus call updateGlobalValue, uint_64_abcd', async () => {
521
+ await dataConverterUint64('uint_64_abcd', '000459b7be58d7ac');
571
522
  });
572
523
 
573
- it('should render device detail, arduino pin call updateGlobalValue, filter out range', async () => {
574
- gatewayData.sensors[0].configs[0].active_filter = 'range';
575
- gatewayData.sensors[0].configs[0].high_level = 10;
576
- await testArduinoPin('config/128282/value/', { v: 11 }, '--', '--');
524
+ test('should render device detail, modbus call updateGlobalValue, uint_64_abcd, data not hex format', async () => {
525
+ await dataConverterWrongData64('uint_64_abcd');
577
526
  });
578
527
 
579
- it('should render device detail, arduino pin call updateGlobalValue, with offset', async () => {
580
- gatewayData.sensors[0].configs[0].ai_trans_offset_value = '1.000';
581
- await testArduinoPin('config/128282/value/', { v: 10 }, 11, '--');
528
+ test('should render device detail, modbus call updateGlobalValue, uint_64_dcba', async () => {
529
+ await dataConverterUint64('uint_64_dcba', 'acd758beb7590400');
582
530
  });
583
531
 
584
- it('should render device detail, arduino pin call updateGlobalValue, with average sample first time', async () => {
585
- const cacheKey = `last_values_${gatewayData.sensors[0].configs[0].id}`;
586
- gatewayData.sensors[0].configs[0].decimal_behind = 2;
587
- gatewayData.sensors[0].configs[0].ai_trans_average_sample = 2;
588
- await testArduinoPin('config/128282/value/', { v: 10 }, 10, '--');
589
- expect(AsyncStorage.setItem).toHaveBeenLastCalledWith(cacheKey, '[10]');
532
+ test('should render device detail, modbus call updateGlobalValue, uint_64_dcba, data not hex format', async () => {
533
+ await dataConverterWrongData64('uint_64_dcba');
590
534
  });
591
535
 
592
- it('should render device detail, arduino pin call updateGlobalValue, with average sample', async () => {
593
- const cacheKey = `last_values_${gatewayData.sensors[0].configs[0].id}`;
594
- await AsyncStorage.setItem(cacheKey, '[0.2, 0.3, 0.4, 0.5]');
595
- gatewayData.sensors[0].configs[0].decimal_behind = 2;
596
- gatewayData.sensors[0].configs[0].ai_trans_average_sample = 2;
597
- await testArduinoPin('config/128282/value/', { v: 10 }, 5.1, '--'); // (10 + 0.2) / 2 = 5.1
598
- expect(AsyncStorage.setItem).toHaveBeenLastCalledWith(
599
- cacheKey,
600
- '[5.1,0.2]'
601
- );
536
+ test('should render device detail, modbus call updateGlobalValue, uint_64_badc', async () => {
537
+ await dataConverterUint64('uint_64_badc', '0400b75958beacd7');
602
538
  });
603
539
 
604
- it('should render device detail, arduino pin call updateGlobalValue, with offset and average sample', async () => {
605
- const cacheKey = `last_values_${gatewayData.sensors[0].configs[0].id}`;
606
- await AsyncStorage.setItem(cacheKey, '[0.2, 0.3, 0.4, 0.5]');
607
- gatewayData.sensors[0].configs[0].decimal_behind = 2;
608
- gatewayData.sensors[0].configs[0].ai_trans_average_sample = 2;
609
- gatewayData.sensors[0].configs[0].ai_trans_offset_value = '1.000';
610
- await testArduinoPin('config/128282/value/', { v: 10 }, 5.6, '--'); // (10 + 1 + 0.2) / 2 = 5.6
611
- expect(AsyncStorage.setItem).toHaveBeenLastCalledWith(
612
- cacheKey,
613
- '[5.6,0.2]'
614
- );
540
+ test('should render device detail, modbus call updateGlobalValue, uint_64_badc, data not hex format', async () => {
541
+ await dataConverterWrongData64('uint_64_badc');
615
542
  });
616
543
 
617
- it('arduino pin submit data type string updateGlobalValue', async () => {
618
- await testArduinoPin('config/128282/value/', { v: 'on' }, 'on', '--');
544
+ test('should render device detail, modbus call updateGlobalValue, uint_64_cdab', async () => {
545
+ await dataConverterUint64('uint_64_cdab', 'd7acbe5859b70004');
619
546
  });
620
547
 
621
- it('should render device detail, arduino pin not call updateGlobalValue, configs is empty', async () => {
622
- gatewayData.sensors = [{ id: configDataFactory.sensor, configs: [] }];
623
- await testArduinoPin('config/128282/value/', { v: 10 }, '--', '--');
548
+ test('should render device detail, modbus call updateGlobalValue, uint_64_cdab, data not hex format', async () => {
549
+ await dataConverterWrongData64('uint_64_cdab');
624
550
  });
625
551
 
626
- it('should render device detail, arduino pin not call updateGlobalValue, sensors is empty', async () => {
627
- gatewayData.sensors = [];
628
- await testArduinoPin('config/128282/value/', { v: 10 }, '--', '--');
629
- });
552
+ const dataConverterInt64 = async (transformer, data) => {
553
+ gatewayData.modbus_gateway.sensors[0].configs[1].transformer = transformer;
554
+ gatewayData.modbus_gateway.sensors[0].configs[1].len = 4;
555
+ gatewayData.modbus_gateway.sensors[0].configs[1].len2 = 4;
630
556
 
631
- // ZIGBEE
632
- const testZigbee = async (expect1, expect2) => {
633
- const valueBoxs = await _receiveDataOnDeviceDetail(
634
- [{ id: 111 }, { id: 222 }],
635
- 'zigbee/0x00158d00022fd3c6/data/',
636
- {
637
- data: { temperature_measured: 36 },
638
- }
639
- );
640
- expect(valueBoxs[0].props.value).toEqual(expect1);
641
- expect(valueBoxs[1].props.value).toEqual(expect2);
557
+ await testModbus(`0001${data}`, 0.1, -122454561422327.6);
642
558
  };
643
559
 
644
- it('should render device detail, zigbee call updateGlobalValue', async () => {
645
- await testZigbee(36, '--');
560
+ test('should render device detail, modbus call updateGlobalValue, int_64_abcd', async () => {
561
+ await dataConverterInt64('int_64_abcd', 'fffba64841a72854');
646
562
  });
647
563
 
648
- it('should render device detail, zigbee call updateGlobalValue, filter zero', async () => {
649
- gatewayData.sensors[2].configs[0].active_filter = 'zero';
650
- const valueBoxs = await _receiveDataOnDeviceDetail(
651
- [{ id: 111 }, { id: 222 }],
652
- 'zigbee/0x00158d00022fd3c6/data/',
653
- {
654
- data: { temperature_measured: 0 },
655
- }
656
- );
657
- expect(valueBoxs[0].props.value).toEqual('--');
658
- expect(valueBoxs[1].props.value).toEqual('--');
564
+ test('should render device detail, modbus call updateGlobalValue, int_64_abcd, data not hex format', async () => {
565
+ await dataConverterWrongData64('int_64_abcd');
659
566
  });
660
567
 
661
- it('should render device detail, zigbee call updateGlobalValue, filter in range', async () => {
662
- gatewayData.sensors[2].configs[0].active_filter = 'range';
663
- gatewayData.sensors[2].configs[0].high_level = 37;
664
- await testZigbee(36, '--');
568
+ test('should render device detail, modbus call updateGlobalValue, int_64_dcba', async () => {
569
+ await dataConverterInt64('int_64_dcba', '5428a74148a6fbff');
665
570
  });
666
571
 
667
- it('should render device detail, zigbee call updateGlobalValue, filter out range', async () => {
668
- gatewayData.sensors[2].configs[0].active_filter = 'range';
669
- gatewayData.sensors[2].configs[0].high_level = 35;
670
- await testZigbee('--', '--');
572
+ test('should render device detail, modbus call updateGlobalValue, int_64_dcba, data not hex format', async () => {
573
+ await dataConverterWrongData64('int_64_dcba');
671
574
  });
672
575
 
673
- it('should render device detail, zigbee call updateGlobalValue, with offset', async () => {
674
- gatewayData.sensors[2].configs[0].ai_trans_offset_value = '1.000';
675
- await testZigbee(37, '--');
576
+ test('should render device detail, modbus call updateGlobalValue, int_64_badc', async () => {
577
+ await dataConverterInt64('int_64_badc', 'fbff48a6a7415428');
676
578
  });
677
579
 
678
- it('should render device detail, zigbee call updateGlobalValue, with average sample first time', async () => {
679
- const cacheKey = `last_values_${gatewayData.sensors[2].configs[0].id}`;
680
- gatewayData.sensors[2].configs[0].decimal_behind = 2;
681
- gatewayData.sensors[2].configs[0].ai_trans_average_sample = 2;
682
- await testZigbee(36, '--');
683
- expect(AsyncStorage.setItem).toHaveBeenLastCalledWith(cacheKey, '[36]');
580
+ test('should render device detail, modbus call updateGlobalValue, int_64_badc, data not hex format', async () => {
581
+ await dataConverterWrongData64('int_64_badc');
684
582
  });
685
583
 
686
- it('should render device detail, zigbee call updateGlobalValue, with average sample', async () => {
687
- const cacheKey = `last_values_${gatewayData.sensors[2].configs[0].id}`;
688
- await AsyncStorage.setItem(cacheKey, '[0.2, 0.3, 0.4, 0.5]');
689
- gatewayData.sensors[2].configs[0].decimal_behind = 2;
690
- gatewayData.sensors[2].configs[0].ai_trans_average_sample = 2;
691
- await testZigbee(18.1, '--'); // (36 + 0.2) / 2 = 18.1
692
- expect(AsyncStorage.setItem).toHaveBeenLastCalledWith(
693
- cacheKey,
694
- '[18.1,0.2]'
695
- );
584
+ test('should render device detail, modbus call updateGlobalValue, int_64_cdab', async () => {
585
+ await dataConverterInt64('int_64_cdab', '285441a7a648fffb');
696
586
  });
697
587
 
698
- it('should render device detail, zigbee call updateGlobalValue, with offset and average sample', async () => {
699
- const cacheKey = `last_values_${gatewayData.sensors[2].configs[0].id}`;
700
- await AsyncStorage.setItem(cacheKey, '[0.2, 0.3, 0.4, 0.5]');
701
- gatewayData.sensors[2].configs[0].decimal_behind = 2;
702
- gatewayData.sensors[2].configs[0].ai_trans_average_sample = 2;
703
- gatewayData.sensors[2].configs[0].ai_trans_offset_value = '1.000';
704
- await testZigbee(18.6, '--'); // (36 + 1 + 0.2) / 2 = 5.6
705
- expect(AsyncStorage.setItem).toHaveBeenLastCalledWith(
706
- cacheKey,
707
- '[18.6,0.2]'
708
- );
588
+ test('should render device detail, modbus call updateGlobalValue, int_64_cdab, data not hex format', async () => {
589
+ await dataConverterWrongData64('int_64_cdab');
709
590
  });
710
591
 
711
- it('should render device detail, zigbee not call updateGlobalValue, configs is empty', async () => {
712
- gatewayData.sensors = [{ id: configDataFactory.sensor, configs: [] }];
713
- await testZigbee('--', '--');
714
- });
592
+ const dataConverterDouble = async (transformer, data) => {
593
+ gatewayData.modbus_gateway.sensors[0].configs[1].transformer = transformer;
594
+ gatewayData.modbus_gateway.sensors[0].configs[1].len = 4;
595
+ gatewayData.modbus_gateway.sensors[0].configs[1].len2 = 4;
596
+ gatewayData.sensors[1].configs[1].decimal_behind = 2;
715
597
 
716
- it('should render device detail, zigbee not call updateGlobalValue, sensors is empty', async () => {
717
- gatewayData.sensors = [];
718
- await testZigbee('--', '--');
719
- });
598
+ await testModbus(`0001${data}`, 0.1, 2.76);
599
+ };
720
600
 
721
- it('should render device detail, zigbee not call updateGlobalValue, zigbee_gateway is empty', async () => {
722
- gatewayData.zigbee_gateway = null;
723
- await testZigbee('--', '--');
601
+ test('should render device detail, modbus call updateGlobalValue, double_abcd', async () => {
602
+ await dataConverterDouble('double_abcd', '403b99999999999a');
724
603
  });
725
604
 
726
- // Third Party
727
- const testThirdParty = async (expect1, expect2) => {
728
- const valueBoxs = await _receiveDataOnDeviceDetail(
729
- [{ id: 37 }, { id: 38 }],
730
- 'third_party/0x00158d00022fd388/data/',
731
- {
732
- led: 1,
733
- }
734
- );
735
- expect(valueBoxs[0].props.value).toEqual(expect1);
736
- expect(valueBoxs[1].props.value).toEqual(expect2);
737
- };
605
+ test('should render device detail, modbus call updateGlobalValue, double_abcd, data not hex format', async () => {
606
+ await dataConverterWrongData64('double_abcd');
607
+ });
738
608
 
739
- it('should render device detail, Third Party call updateGlobalValue', async () => {
740
- await testThirdParty(1, '--');
609
+ test('should render device detail, modbus call updateGlobalValue, double_dcba', async () => {
610
+ await dataConverterDouble('double_dcba', '9a99999999993b40');
741
611
  });
742
612
 
743
- it('should render device detail, Third Party call updateGlobalValue, filter zero', async () => {
744
- gatewayData.sensors[3].configs[0].active_filter = 'zero';
745
- const valueBoxs = await _receiveDataOnDeviceDetail(
746
- [{ id: 37 }, { id: 38 }],
747
- 'third_party/0x00158d00022fd388/data/',
748
- {
749
- led: 0,
750
- }
751
- );
752
- expect(valueBoxs[0].props.value).toEqual('--');
753
- expect(valueBoxs[1].props.value).toEqual('--');
613
+ test('should render device detail, modbus call updateGlobalValue, double_dcba, data not hex format', async () => {
614
+ await dataConverterWrongData64('double_dcba');
754
615
  });
755
616
 
756
- it('should render device detail, Third Party call updateGlobalValue, filter in range', async () => {
757
- gatewayData.sensors[3].configs[0].active_filter = 'range';
758
- gatewayData.sensors[3].configs[0].high_level = 2;
759
- await testThirdParty(1, '--');
617
+ test('should render device detail, modbus call updateGlobalValue, double_badc', async () => {
618
+ await dataConverterDouble('double_badc', '3b40999999999a99');
760
619
  });
761
620
 
762
- it('should render device detail, Third Party call updateGlobalValue, filter out range', async () => {
763
- gatewayData.sensors[3].configs[0].active_filter = 'range';
764
- gatewayData.sensors[3].configs[0].high_level = 0.5;
765
- await testThirdParty('--', '--');
621
+ test('should render device detail, modbus call updateGlobalValue, double_badc, data not hex format', async () => {
622
+ await dataConverterWrongData64('double_badc');
766
623
  });
767
624
 
768
- it('should render device detail, Third Party call updateGlobalValue, with offset', async () => {
769
- gatewayData.sensors[3].configs[0].ai_trans_offset_value = '1.000';
770
- await testThirdParty(2, '--');
625
+ test('should render device detail, modbus call updateGlobalValue, double_cdab', async () => {
626
+ await dataConverterDouble('double_cdab', '999a99999999403b');
771
627
  });
772
628
 
773
- it('should render device detail, Third Party call updateGlobalValue, with average sample first time', async () => {
774
- const cacheKey = `last_values_${gatewayData.sensors[3].configs[0].id}`;
775
- gatewayData.sensors[3].configs[0].decimal_behind = 2;
776
- gatewayData.sensors[3].configs[0].ai_trans_average_sample = 2;
777
- await testThirdParty(1, '--');
778
- expect(AsyncStorage.setItem).toHaveBeenLastCalledWith(cacheKey, '[1]');
629
+ test('should render device detail, modbus call updateGlobalValue, double_cdab, data not hex format', async () => {
630
+ await dataConverterWrongData64('double_cdab');
779
631
  });
780
632
 
781
- it('should render device detail, Third Party call updateGlobalValue, with average sample', async () => {
782
- const cacheKey = `last_values_${gatewayData.sensors[3].configs[0].id}`;
783
- await AsyncStorage.setItem(cacheKey, '[0.2, 0.3, 0.4, 0.5]');
784
- gatewayData.sensors[3].configs[0].decimal_behind = 2;
785
- gatewayData.sensors[3].configs[0].ai_trans_average_sample = 2;
786
- await testThirdParty(0.6, '--'); // (1 + 0.2) / 2 = 0.6
787
- expect(AsyncStorage.setItem).toHaveBeenLastCalledWith(
788
- cacheKey,
789
- '[0.6,0.2]'
790
- );
633
+ const _watchDataChipsOnDeviceDetail = async (
634
+ data,
635
+ expect1,
636
+ expect2,
637
+ last_updated = '2025-09-09T12:00:00Z'
638
+ ) => {
639
+ mock.onGet(API.CHIP.JSON_CONFIGURATION).reply(200, []);
640
+ mock.onPost(API.IOT.CHIP_MANAGER.WATCH_DATA_CHIPS()).reply(200, {
641
+ 7689: {
642
+ last_modbus_data: {
643
+ data,
644
+ ack: '11',
645
+ last_updated,
646
+ },
647
+ },
648
+ });
649
+ mock.onGet(API.CHIP.SHARED_CONFIGURATION).reply(200, [gatewayData]);
650
+
651
+ const responseDisplay = {
652
+ items: [
653
+ {
654
+ id: 1,
655
+ order: 0,
656
+ template: 'value',
657
+ type: 'value',
658
+ configuration: {
659
+ template: 'simple_list',
660
+ configs: [{ id: 128323 }, { id: 128324 }],
661
+ },
662
+ },
663
+ ],
664
+ };
665
+
666
+ const responseRemoteControl = {
667
+ bluetooth: {
668
+ address: 'JUvfa06PMDU8Cqlo',
669
+ password: 'MYcNoskxspWTPsnh',
670
+ },
671
+ internet: {},
672
+ };
673
+
674
+ const responseDisplayValueV2 = {
675
+ configs: [],
676
+ is_connected: true,
677
+ last_updated: '2021-01-24T12:00:00.000Z',
678
+ };
679
+
680
+ mockAxios(responseDisplay, responseDisplayValueV2, responseRemoteControl);
681
+
682
+ await act(async () => {
683
+ tree = await create(
684
+ wrapComponent(store, account, {
685
+ ...route,
686
+ params: { ...route.params },
687
+ })
688
+ );
689
+ });
690
+
691
+ const instance = tree.root;
692
+ const valueBoxs = instance.findAllByType(QualityIndicatorItem);
693
+ expect(valueBoxs[0].props.value).toEqual(expect1);
694
+ expect(valueBoxs[1].props.value).toEqual(expect2);
695
+
696
+ expect(
697
+ mock.history.post.filter(
698
+ (req) => req.url === API.IOT.CHIP_MANAGER.WATCH_DATA_CHIPS()
699
+ )
700
+ ).toHaveLength(1);
701
+
702
+ await act(async () => {
703
+ jest.runOnlyPendingTimers();
704
+ });
705
+ expect(
706
+ mock.history.post.filter(
707
+ (req) => req.url === API.IOT.CHIP_MANAGER.WATCH_DATA_CHIPS()
708
+ )
709
+ ).toHaveLength(2);
710
+ expect(unwatchMultiDataChips).not.toHaveBeenCalled();
711
+
712
+ await act(async () => {
713
+ await tree.unmount();
714
+ });
715
+ expect(unwatchMultiDataChips).toHaveBeenCalledWith([gatewayData.id]);
716
+ };
717
+
718
+ it('should render device detail, watch data chips call updateGlobalValue', async () => {
719
+ await _watchDataChipsOnDeviceDetail('00010002', 0.1, 0.2);
791
720
  });
792
721
 
793
- it('should render device detail, Third Party call updateGlobalValue, with offset and average sample', async () => {
794
- const cacheKey = `last_values_${gatewayData.sensors[3].configs[0].id}`;
795
- await AsyncStorage.setItem(cacheKey, '[0.2, 0.3, 0.4, 0.5]');
796
- gatewayData.sensors[3].configs[0].decimal_behind = 2;
797
- gatewayData.sensors[3].configs[0].ai_trans_average_sample = 2;
798
- gatewayData.sensors[3].configs[0].ai_trans_offset_value = '1.000';
799
- await testThirdParty(1.1, '--'); // (1 + 1 + 0.2) / 2 = 1.1
800
- expect(AsyncStorage.setItem).toHaveBeenLastCalledWith(
801
- cacheKey,
802
- '[1.1,0.2]'
803
- );
722
+ it('should render device detail, watch data chips call updateGlobalValue with past last_updated', async () => {
723
+ act(() => {
724
+ setConfigGlobalState('configValues', {
725
+ 128323: { value: 0, last_updated: moment('2025-09-09T12:00:01Z') },
726
+ 128324: { value: 0, last_updated: moment('2025-09-09T12:00:01Z') },
727
+ });
728
+ });
729
+ await _watchDataChipsOnDeviceDetail('00010002', 0, 0);
804
730
  });
805
731
 
806
- it('should render device detail, Third Party not call updateGlobalValue, configs is empty', async () => {
807
- gatewayData.sensors = [{ id: configDataFactory.sensor, configs: [] }];
808
- await testThirdParty('--', '--');
732
+ it('should render device detail, watch data chips call updateGlobalValue with future last_updated', async () => {
733
+ act(() => {
734
+ setConfigGlobalState('configValues', {
735
+ 128323: { value: 0, last_updated: moment('2025-09-09T11:59:59Z') },
736
+ 128324: { value: 0, last_updated: moment('2025-09-09T11:59:59Z') },
737
+ });
738
+ });
739
+ await _watchDataChipsOnDeviceDetail('00010002', 0.1, 0.2);
809
740
  });
810
741
 
811
- it('should render device detail, Third Party not call updateGlobalValue, sensors is empty', async () => {
812
- gatewayData.sensors = [];
813
- await testThirdParty('--', '--');
742
+ it('should render device detail, watch data chips with edge past last_updated', async () => {
743
+ act(() => {
744
+ setConfigGlobalState('configValues', {
745
+ 128323: {
746
+ value: 0,
747
+ last_updated: moment('2025-09-09T12:00:00.123457Z'),
748
+ last_updated_micro: 457,
749
+ },
750
+ 128324: {
751
+ value: 0,
752
+ last_updated: moment('2025-09-09T12:00:00.123457Z'),
753
+ last_updated_micro: 457,
754
+ },
755
+ });
756
+ });
757
+ await _watchDataChipsOnDeviceDetail(
758
+ '00010002',
759
+ 0,
760
+ 0,
761
+ '2025-09-09T12:00:00.123456Z'
762
+ );
814
763
  });
815
764
 
816
- it('should render device detail, Third Party not call updateGlobalValue, third_party_gateway is empty', async () => {
817
- gatewayData.third_party_gateway = null;
818
- await testThirdParty('--', '--');
765
+ it('should render device detail, watch data chips with edge future last_updated', async () => {
766
+ act(() => {
767
+ setConfigGlobalState('configValues', {
768
+ 128323: {
769
+ value: 0,
770
+ last_updated: moment('2025-09-09T12:00:00.123455Z'),
771
+ last_updated_micro: 455,
772
+ },
773
+ 128324: {
774
+ value: 0,
775
+ last_updated: moment('2025-09-09T12:00:00.123455Z'),
776
+ last_updated_micro: 455,
777
+ },
778
+ });
779
+ });
780
+ await _watchDataChipsOnDeviceDetail(
781
+ '00010002',
782
+ 0.1,
783
+ 0.2,
784
+ '2025-09-09T12:00:00.123456Z'
785
+ );
819
786
  });
820
787
  });