@eohjsc/react-native-smart-city 0.3.77 → 0.3.79

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,7 +1,7 @@
1
1
  {
2
2
  "name": "@eohjsc/react-native-smart-city",
3
3
  "title": "React Native Smart Home",
4
- "version": "0.3.77",
4
+ "version": "0.3.79",
5
5
  "description": "TODO",
6
6
  "main": "index.js",
7
7
  "files": [
@@ -105,7 +105,7 @@ const OptionsDropdownActionTemplate = ({
105
105
  if (!config) {
106
106
  return t('not_available');
107
107
  }
108
- return selectedOption.text;
108
+ return selectedOption?.text;
109
109
  }, [config, selectedOption?.text, t]);
110
110
 
111
111
  const iconSvg = useMemo(() => {
@@ -190,7 +190,7 @@ const OptionsDropdownActionTemplate = ({
190
190
  setSelectedIndex(index);
191
191
  }}
192
192
  >
193
- <Text style={styles.text}>{item.text}</Text>
193
+ <Text style={styles.text}>{item?.text}</Text>
194
194
  </TouchableOpacity>
195
195
  </View>
196
196
  ))}
@@ -214,6 +214,7 @@ const TimerActionTemplate = ({ actionGroup = {}, doAction, sensor = {} }) => {
214
214
  onConfirm={onConfirmTime}
215
215
  onCancel={onHideTime}
216
216
  display="spinner"
217
+ headerTextIOS={t('pick_a_date')}
217
218
  cancelTextIOS={t('cancel')}
218
219
  confirmTextIOS={t('confirm')}
219
220
  />
@@ -49,7 +49,7 @@ const FlatListItems = memo(({ data, style, title, offsetTitle }) => {
49
49
  key={item?.id}
50
50
  standard={item.standard}
51
51
  value={item.value}
52
- measure={item.measure}
52
+ measure={item.unit}
53
53
  evaluate={item.evaluate}
54
54
  style={styles.boxStatus}
55
55
  descriptionScreen={Routes.TDSGuide}
@@ -241,6 +241,7 @@ const HistoryChart = memo(
241
241
  onConfirm={onConfirmStart}
242
242
  onCancel={onCancel}
243
243
  display="spinner"
244
+ headerTextIOS={t('pick_a_date')}
244
245
  cancelTextIOS={t('cancel')}
245
246
  confirmTextIOS={t('confirm')}
246
247
  />
@@ -251,6 +252,7 @@ const HistoryChart = memo(
251
252
  onConfirm={onConfirmEnd}
252
253
  onCancel={onCancel}
253
254
  display="spinner"
255
+ headerTextIOS={t('pick_a_date')}
254
256
  cancelTextIOS={t('cancel')}
255
257
  confirmTextIOS={t('confirm')}
256
258
  />
@@ -21,7 +21,7 @@ const PMSensorIndicator = memo(({ data = [], style }) => {
21
21
  standard={item.standard}
22
22
  value={getValue}
23
23
  evaluate={item.evaluate}
24
- measure={item.measure}
24
+ measure={item.unit}
25
25
  style={style}
26
26
  />
27
27
  );
@@ -17,7 +17,7 @@ const ListQualityIndicator = ({ data, style }) => {
17
17
  standard={item.standard}
18
18
  value={getValue}
19
19
  evaluate={item.evaluate}
20
- measure={item.measure}
20
+ measure={item.unit}
21
21
  />
22
22
  );
23
23
  }, []);
@@ -53,7 +53,7 @@ const API = {
53
53
  },
54
54
  DEVICE: {
55
55
  SENSOR_DETAIL: (id) => `/property_manager/sensors/${id}/`,
56
- DISPLAY: (id) => `/property_manager/sensors/${id}/display/`,
56
+ DISPLAY: (id) => `/property_manager/devices/${id}/display/`,
57
57
  SIDE_MENU_DETAIL: (id, side_menu_id) =>
58
58
  `/property_manager/devices/${id}/display/side_menu/${side_menu_id}/`,
59
59
  DISPLAY_VALUES_V2: (id) =>
@@ -2,6 +2,7 @@ import React from 'react';
2
2
  import { act, renderHook } from '@testing-library/react-hooks';
3
3
  import { useRemoteControl } from '../index';
4
4
  import {
5
+ BLUETOOOH_DEVICE_UNSTABLE,
5
6
  sendCommandOverBluetooth,
6
7
  SEND_COMMAND_OVER_BLUETOOTH_FAIL,
7
8
  } from '../../../iot/RemoteControl/Bluetooth';
@@ -91,7 +92,7 @@ describe('Test useRemoteControl', () => {
91
92
  });
92
93
 
93
94
  sendCommandOverBluetooth.mockImplementation(() => {
94
- throw SEND_COMMAND_OVER_BLUETOOTH_FAIL;
95
+ return SEND_COMMAND_OVER_BLUETOOTH_FAIL;
95
96
  });
96
97
  sendCommandOverInternet.mockImplementation(async () => true);
97
98
  await act(async () => {
@@ -109,7 +110,7 @@ describe('Test useRemoteControl', () => {
109
110
  data,
110
111
  'bluetooth'
111
112
  );
112
- expect(sendCommandOverInternet).toBeCalledTimes(6);
113
+ expect(sendCommandOverInternet).toBeCalledTimes(1);
113
114
  expect(sendCommandOverHomeAssistant).not.toBeCalled();
114
115
  });
115
116
 
@@ -127,7 +128,7 @@ describe('Test useRemoteControl', () => {
127
128
  });
128
129
 
129
130
  sendCommandOverBluetooth.mockImplementation(() => {
130
- throw SEND_COMMAND_OVER_BLUETOOTH_FAIL;
131
+ return SEND_COMMAND_OVER_BLUETOOTH_FAIL;
131
132
  });
132
133
  sendCommandOverInternet.mockImplementation(async () => true);
133
134
  await act(async () => {
@@ -176,7 +177,6 @@ describe('Test useRemoteControl', () => {
176
177
  data,
177
178
  userId
178
179
  );
179
- expect(sendCommandOverInternet).toBeCalled();
180
180
  expect(sendCommandOverHomeAssistant).not.toBeCalled();
181
181
  });
182
182
 
@@ -244,4 +244,57 @@ describe('Test useRemoteControl', () => {
244
244
  expect(sendCommandOverHomeAssistant).not.toBeCalled();
245
245
  expect(sendCommandOverBluetooth).not.toBeCalled();
246
246
  });
247
+
248
+ it('test send remote command via bluetooth case when bluetooh device unstable', async () => {
249
+ action.command_prefer_over_bluetooth = true;
250
+ action.command_prefer_over_internet = false;
251
+ const { result: sendRemoteCommand } = renderHook(() => useRemoteControl(), {
252
+ wrapper,
253
+ });
254
+
255
+ sendCommandOverBluetooth.mockImplementation(() => {
256
+ return BLUETOOOH_DEVICE_UNSTABLE;
257
+ });
258
+ await act(async () => {
259
+ await sendRemoteCommand.current(sensor, action, data, userId);
260
+ });
261
+ expect(sendCommandOverBluetooth).toBeCalledWith(
262
+ sensor,
263
+ action,
264
+ data,
265
+ userId
266
+ );
267
+ expect(sendCommandOverBluetooth).toBeCalledTimes(6);
268
+ });
269
+
270
+ // eslint-disable-next-line max-len
271
+ it('test send remote command via bluetooth case when bluetooh device unstable 5 times will switch send internet', async () => {
272
+ action.command_prefer_over_bluetooth = true;
273
+ action.command_prefer_over_internet = false;
274
+ const { result: sendRemoteCommand } = renderHook(() => useRemoteControl(), {
275
+ wrapper,
276
+ });
277
+
278
+ sendCommandOverBluetooth.mockImplementation(() => {
279
+ return BLUETOOOH_DEVICE_UNSTABLE;
280
+ });
281
+ sendCommandOverInternet.mockImplementation(async () => true);
282
+ await act(async () => {
283
+ await sendRemoteCommand.current(sensor, action, data, userId);
284
+ });
285
+ expect(sendCommandOverBluetooth).toBeCalledWith(
286
+ sensor,
287
+ action,
288
+ data,
289
+ userId
290
+ );
291
+ expect(sendCommandOverInternet).toBeCalledWith(
292
+ sensor,
293
+ action,
294
+ data,
295
+ 'bluetooth'
296
+ );
297
+ expect(sendCommandOverBluetooth).toBeCalledTimes(6);
298
+ expect(sendCommandOverInternet).toBeCalledTimes(1);
299
+ });
247
300
  });
@@ -6,18 +6,25 @@ import { sendCommandOverInternet } from '../../iot/RemoteControl/Internet';
6
6
  import {
7
7
  sendCommandOverBluetooth,
8
8
  SEND_COMMAND_OVER_BLUETOOTH_FAIL,
9
+ BLUETOOOH_DEVICE_UNSTABLE,
9
10
  } from '../../iot/RemoteControl/Bluetooth';
10
11
  import { ToastBottomHelper } from '../../utils/Utils';
11
12
  import { t } from 'i18n-js';
12
13
  import NetInfo from '@react-native-community/netinfo';
13
14
 
14
- let count = 0;
15
-
16
- const onRetry = (callback) => {
17
- const to = setTimeout(() => {
18
- callback;
19
- clearTimeout(to);
20
- }, 200);
15
+ const handleReconnectionDeviceBle = async (device, action, data, userId) => {
16
+ for (let i = 0; i < 5; i++) {
17
+ let promise = new Promise((resolve) =>
18
+ setTimeout(() => {
19
+ resolve(sendCommandOverBluetooth(device, action, data, userId));
20
+ }, 200)
21
+ );
22
+ const resultPromise = await promise;
23
+ if (resultPromise === true) {
24
+ return resultPromise;
25
+ }
26
+ }
27
+ return SEND_COMMAND_OVER_BLUETOOTH_FAIL;
21
28
  };
22
29
 
23
30
  const useRemoteControl = () => {
@@ -36,47 +43,31 @@ const useRemoteControl = () => {
36
43
  return result;
37
44
  }
38
45
 
39
- if (action.command_prefer_over_bluetooth && count < 5) {
40
- count++;
41
- try {
42
- const res = await sendCommandOverBluetooth(
43
- device,
44
- action,
45
- data,
46
- userId
47
- );
48
- if (res) {
49
- count = 0;
50
- return res;
51
- } else {
52
- onRetry(sendRemoteCommand(device, action, data, userId));
53
- }
54
- } catch (err) {
55
- onRetry(sendRemoteCommand(device, action, data, userId));
46
+ if (action.command_prefer_over_bluetooth) {
47
+ let res = await sendCommandOverBluetooth(device, action, data, userId);
48
+ if (res === BLUETOOOH_DEVICE_UNSTABLE) {
49
+ res = await handleReconnectionDeviceBle(device, action, data, userId);
50
+ }
51
+ if (res === SEND_COMMAND_OVER_BLUETOOTH_FAIL) {
56
52
  const netState = await NetInfo.fetch();
57
53
  if (netState.isConnected) {
58
54
  result = false;
59
-
60
- if (err === SEND_COMMAND_OVER_BLUETOOTH_FAIL) {
61
- // Checking only bluetooth: not force internet
62
- if (!action.is_only_bluetooth) {
63
- result = await sendCommandOverInternet(
64
- device,
65
- action,
66
- data,
67
- 'bluetooth'
68
- );
69
- }
70
- return result;
71
- } else {
72
- throw err;
55
+ // Checking only bluetooth: not force internet
56
+ if (!action.is_only_bluetooth) {
57
+ result = await sendCommandOverInternet(
58
+ device,
59
+ action,
60
+ data,
61
+ 'bluetooth'
62
+ );
73
63
  }
64
+ return result;
74
65
  } else {
75
66
  return false;
76
67
  }
77
68
  }
69
+ return res;
78
70
  }
79
- count = 0;
80
71
  // Checking only bluetooth: not other options
81
72
  if (action.is_only_bluetooth) {
82
73
  ToastBottomHelper.error(
@@ -15,6 +15,8 @@ let isScanning = false;
15
15
  export const SEND_COMMAND_OVER_BLUETOOTH_FAIL =
16
16
  'SEND_COMMAND_OVER_BLUETOOTH_FAIL';
17
17
 
18
+ export const BLUETOOOH_DEVICE_UNSTABLE = 'BLUETOOOH_DEVICE_UNSTABLE';
19
+
18
20
  export const clearNeedToScanDevices = () => {
19
21
  needToScanDevices.length = 0;
20
22
  };
@@ -144,7 +146,7 @@ export const sendDataOverBluetooth = async (
144
146
  keepConnect = false
145
147
  ) => {
146
148
  if (!device) {
147
- throw SEND_COMMAND_OVER_BLUETOOTH_FAIL;
149
+ return SEND_COMMAND_OVER_BLUETOOTH_FAIL;
148
150
  }
149
151
 
150
152
  ToastBottomHelper.error(t('Sending command via bluetooth'));
@@ -155,6 +157,20 @@ export const sendDataOverBluetooth = async (
155
157
 
156
158
  try {
157
159
  connectedDevice = await device.connect();
160
+ } catch (e) {
161
+ const BLE_ERROR = {
162
+ DEVICE_IS_NOT_ALREADY_CONNECTED: 201,
163
+ DEVICE_WAS_DISCONNECTED: 203,
164
+ };
165
+ if (
166
+ e?.errorCode === BLE_ERROR.DEVICE_IS_NOT_ALREADY_CONNECTED ||
167
+ BLE_ERROR.DEVICE_WAS_DISCONNECTED
168
+ ) {
169
+ await bleManager.cancelDeviceConnection(device.id);
170
+ return BLUETOOOH_DEVICE_UNSTABLE;
171
+ }
172
+ }
173
+ try {
158
174
  fullDataDevice =
159
175
  await connectedDevice.discoverAllServicesAndCharacteristics();
160
176
  await fullDataDevice.monitorCharacteristicForService(
@@ -170,8 +186,10 @@ export const sendDataOverBluetooth = async (
170
186
  await connectedDevice.cancelConnection();
171
187
  }
172
188
  } else if (notify === BLE.BLE_RESPONSE_FAILED) {
189
+ await connectedDevice.cancelConnection();
173
190
  ToastBottomHelper.error(t('control_device_via_bluetooth_failed'));
174
191
  }
192
+ await bleManager.cancelTransaction(BLE.BLE_LISTER_RESPONSE_CONTROL);
175
193
  },
176
194
  BLE.BLE_LISTER_RESPONSE_CONTROL
177
195
  );
@@ -184,7 +202,7 @@ export const sendDataOverBluetooth = async (
184
202
  } catch (e) {
185
203
  await connectedDevice.cancelConnection();
186
204
  ToastBottomHelper.error(t('command_is_fail_to_send_via_bluetooth'));
187
- throw SEND_COMMAND_OVER_BLUETOOTH_FAIL;
205
+ return SEND_COMMAND_OVER_BLUETOOTH_FAIL;
188
206
  }
189
207
 
190
208
  if (keepConnect) {
@@ -257,6 +257,7 @@ const FilterPopup = ({
257
257
  onCancel={onPickerCancel}
258
258
  onHide={releaseLockShowing}
259
259
  display="spinner"
260
+ headerTextIOS={t('pick_a_date')}
260
261
  cancelTextIOS={t('cancel')}
261
262
  confirmTextIOS={t('confirm')}
262
263
  />
@@ -169,7 +169,7 @@ const SelectAction = memo(({ route }) => {
169
169
  Alert.alert('', t('choose_only_one'));
170
170
  return;
171
171
  }
172
- if (isSelectSensor || isSetupEvent) {
172
+ if (isSelectSensor || sensorData?.length > 0) {
173
173
  await checkConditionToContinue();
174
174
  } else {
175
175
  if (automateId) {
@@ -52,7 +52,7 @@ const ConnectingDevice = ({
52
52
 
53
53
  useEffect(() => {
54
54
  timeout = setTimeout(() => {
55
- Alert.alert(t('continue_to_wait'), t('it_has_been_5_minutes'), [
55
+ Alert.alert(t('continue_to_wait'), t('it_has_been_2_minutes'), [
56
56
  {
57
57
  text: t('back'),
58
58
  onPress: goBack,
@@ -2,8 +2,6 @@ import React, { memo, useCallback, useEffect, useState, useMemo } from 'react';
2
2
  import { ScrollView, TouchableOpacity, View } from 'react-native';
3
3
  import { IconOutline } from '@ant-design/icons-react-native';
4
4
  import { CommonActions, useNavigation } from '@react-navigation/native';
5
- import debounce from 'lodash.debounce';
6
-
7
5
  import { useTranslations } from '../../hooks/Common/useTranslations';
8
6
  import { Colors } from '../../configs';
9
7
  import Text from '../../commons/Text';
@@ -16,6 +14,8 @@ import { axiosGet, axiosPost } from '../../utils/Apis/axios';
16
14
  import API from '../../configs/API';
17
15
  import { HeaderCustom } from '../../commons/Header';
18
16
  import IconComponent from '../../commons/IconComponent';
17
+ import FullLoading from '../../commons/FullLoading';
18
+ import { ToastBottomHelper } from '../../utils/Utils';
19
19
 
20
20
  const RenameNewDevices = memo(({ route }) => {
21
21
  const t = useTranslations();
@@ -26,6 +26,9 @@ const RenameNewDevices = memo(({ route }) => {
26
26
  const [selectedItem, setSelectedItem] = useState({});
27
27
  const [isCanRename, setIsCanRename] = useState(false);
28
28
  const [info, setInfo] = useState({});
29
+ const [loading, setLoading] = useState(false);
30
+ const [isChangedName, setIsChangedName] = useState(false);
31
+ const [isDisabled, setIsDisabled] = useState(false);
29
32
 
30
33
  const renameLabel = AccessibilityLabel.CONNECTED_DEVICE_RENAME_DEVICE;
31
34
 
@@ -50,40 +53,55 @@ const RenameNewDevices = memo(({ route }) => {
50
53
  return baseHeight + contentItems * 25;
51
54
  }, [addDeviceType, info.sensors]);
52
55
 
53
- const callApiRenameDevices = useCallback(async () => {
54
- const { success } = await axiosPost(API.CHIP.RENAME_DEVICES(info.id), info);
55
- if (success) {
56
- const resetAction = CommonActions.reset({
57
- index: 0,
58
- routes: [
59
- {
60
- name: Routes.Main,
56
+ const goBackUnitDetail = useCallback(() => {
57
+ const resetAction = CommonActions.reset({
58
+ index: 0,
59
+ routes: [
60
+ {
61
+ name: Routes.Main,
62
+ params: {
63
+ screen: Routes.DashboardStack,
61
64
  params: {
62
- screen: Routes.DashboardStack,
63
- params: {
64
- screen: Routes.Dashboard,
65
- },
65
+ screen: Routes.Dashboard,
66
66
  },
67
67
  },
68
- {
69
- name: Routes.UnitStack,
68
+ },
69
+ {
70
+ name: Routes.UnitStack,
71
+ params: {
72
+ screen: Routes.UnitDetail,
70
73
  params: {
71
- screen: Routes.UnitDetail,
72
- params: {
73
- unitId: unit?.id,
74
- stationId: subUnit?.id,
75
- isSuccessfullyConnected: true,
76
- routeName: Routes.DashboardStack,
77
- },
74
+ unitId: unit?.id,
75
+ stationId: subUnit?.id,
76
+ isSuccessfullyConnected: true,
77
+ routeName: Routes.DashboardStack,
78
78
  },
79
79
  },
80
- ],
81
- });
82
- dispatch(resetAction);
83
- }
84
- }, [dispatch, info, subUnit?.id, unit?.id]);
80
+ },
81
+ ],
82
+ });
83
+ dispatch(resetAction);
84
+ }, [dispatch, subUnit?.id, unit?.id]);
85
85
 
86
- const onPressDone = debounce(() => callApiRenameDevices(), 2000);
86
+ const onPressDone = useCallback(async () => {
87
+ if (!isChangedName) {
88
+ setIsDisabled(true);
89
+ const clear = setTimeout(() => {
90
+ setIsDisabled(false);
91
+ clearTimeout(clear);
92
+ }, 3000);
93
+ goBackUnitDetail();
94
+ return;
95
+ }
96
+ setLoading(true);
97
+ const { success } = await axiosPost(API.CHIP.RENAME_DEVICES(info.id), info);
98
+ if (success) {
99
+ goBackUnitDetail();
100
+ } else {
101
+ ToastBottomHelper.error(t('rename_device_fail'));
102
+ }
103
+ setLoading(false);
104
+ }, [goBackUnitDetail, info, isChangedName, t]);
87
105
 
88
106
  useEffect(() => {
89
107
  (async () => {
@@ -104,6 +122,7 @@ const RenameNewDevices = memo(({ route }) => {
104
122
  }, [chipId, sensorId, subUnit]);
105
123
 
106
124
  const updateItemName = (type, sensor_index, end_device_index) => (value) => {
125
+ setIsChangedName(!!value);
107
126
  setInfo((currentInfo) => {
108
127
  if (type === 'chip') {
109
128
  return { ...currentInfo, name: value };
@@ -260,10 +279,12 @@ const RenameNewDevices = memo(({ route }) => {
260
279
  </Text>
261
280
  </View>
262
281
  </View>
282
+ {loading && <FullLoading />}
263
283
  <TouchableOpacity
264
284
  style={styles.btnDone}
265
285
  onPress={onPressDone}
266
286
  accessibilityLabel={AccessibilityLabel.BUTTON_DONE}
287
+ disabled={isDisabled}
267
288
  >
268
289
  <Text semibold size={16} color={Colors.Primary}>
269
290
  {t('done')}
@@ -24,8 +24,6 @@ const mockedNavigate = jest.fn();
24
24
  const mockedGoBack = jest.fn();
25
25
  const mockedDispatch = jest.fn();
26
26
 
27
- jest.mock('lodash.debounce', () => jest.fn((fn) => fn));
28
-
29
27
  jest.mock('@react-navigation/native', () => {
30
28
  return {
31
29
  ...jest.requireActual('@react-navigation/native'),
@@ -47,6 +45,62 @@ describe('Test rename new devices', () => {
47
45
  `${AccessibilityLabel.CONNECTED_DEVICE_RENAME_DEVICE}_LIST_ITEM_RENAME`
48
46
  );
49
47
  };
48
+ const routeTree = (type) => {
49
+ switch (type) {
50
+ case 'wifi':
51
+ route = {
52
+ params: {
53
+ unitId: 1,
54
+ sensorId: 1,
55
+ stationId: 2,
56
+ chipId: 3,
57
+ qrData: {},
58
+ addDeviceType: 'wifi',
59
+ },
60
+ };
61
+ break;
62
+ case 'gateway':
63
+ route = {
64
+ params: {
65
+ unitId: 1,
66
+ stationId: 2,
67
+ chipId: 3,
68
+ qrData: {},
69
+ addDeviceType: 'gateway',
70
+ },
71
+ };
72
+ break;
73
+ }
74
+ };
75
+ const mockedDispatchNavigate = () => {
76
+ expect(mockedDispatch).toBeCalledWith({
77
+ payload: {
78
+ index: 0,
79
+ routes: [
80
+ {
81
+ name: 'Main',
82
+ params: {
83
+ params: { screen: 'Dashboard' },
84
+ screen: 'DashboardStack',
85
+ },
86
+ },
87
+ {
88
+ name: 'UnitStack',
89
+ params: {
90
+ params: {
91
+ isSuccessfullyConnected: true,
92
+ routeName: 'DashboardStack',
93
+ stationId: undefined,
94
+ unitId: undefined,
95
+ },
96
+ screen: 'UnitDetail',
97
+ },
98
+ },
99
+ ],
100
+ },
101
+ type: 'RESET',
102
+ });
103
+ };
50
104
  const onPressToRename = async (instance) => {
51
105
  const button = instance.findAll(
52
106
  (el) =>
@@ -77,15 +131,7 @@ describe('Test rename new devices', () => {
77
131
  });
78
132
 
79
133
  it('rendering base', async () => {
80
- route = {
81
- params: {
82
- unitId: 1,
83
- stationId: 2,
84
- chipId: 3,
85
- qrData: {},
86
- addDeviceType: 'gateway',
87
- },
88
- };
134
+ routeTree('gateway');
89
135
  mock.onGet().reply(200, {
90
136
  id: 1,
91
137
  name: 'chip',
@@ -126,16 +172,7 @@ describe('Test rename new devices', () => {
126
172
  });
127
173
 
128
174
  it('rendering one end device', async () => {
129
- route = {
130
- params: {
131
- unitId: 1,
132
- sensorId: 1,
133
- stationId: 2,
134
- chipId: 3,
135
- qrData: {},
136
- addDeviceType: 'wifi',
137
- },
138
- };
175
+ routeTree('wifi');
139
176
  mock.onGet().reply(200, {
140
177
  id: 1,
141
178
  name: 'chip',
@@ -162,16 +199,7 @@ describe('Test rename new devices', () => {
162
199
  });
163
200
 
164
201
  it('rendering two end device', async () => {
165
- route = {
166
- params: {
167
- unitId: 1,
168
- sensorId: 1,
169
- stationId: 2,
170
- chipId: 3,
171
- qrData: {},
172
- addDeviceType: 'wifi',
173
- },
174
- };
202
+ routeTree('wifi');
175
203
  mock.onGet().reply(200, {
176
204
  id: 1,
177
205
  name: 'chip',
@@ -202,16 +230,7 @@ describe('Test rename new devices', () => {
202
230
  });
203
231
 
204
232
  it('rendering three end device', async () => {
205
- route = {
206
- params: {
207
- unitId: 1,
208
- sensorId: 1,
209
- stationId: 2,
210
- chipId: 3,
211
- qrData: {},
212
- addDeviceType: 'wifi',
213
- },
214
- };
233
+ routeTree('wifi');
215
234
  mock.onGet().reply(200, {
216
235
  id: 1,
217
236
  name: 'chip',
@@ -251,15 +270,7 @@ describe('Test rename new devices', () => {
251
270
  id: 1,
252
271
  name: 'chip',
253
272
  });
254
- route = {
255
- params: {
256
- unitId: 1,
257
- stationId: 2,
258
- chipId: 3,
259
- qrData: {},
260
- addDeviceType: 'gateway',
261
- },
262
- };
273
+ routeTree('gateway');
263
274
  await act(async () => {
264
275
  tree = await create(wrapComponent(route));
265
276
  });
@@ -289,15 +300,7 @@ describe('Test rename new devices', () => {
289
300
  id: 1,
290
301
  can_rename: true,
291
302
  });
292
- route = {
293
- params: {
294
- unitId: 1,
295
- stationId: 2,
296
- chipId: 3,
297
- qrData: {},
298
- addDeviceType: 'gateway',
299
- },
300
- };
303
+ routeTree('gateway');
301
304
  await act(async () => {
302
305
  tree = await create(wrapComponent(route));
303
306
  });
@@ -396,32 +399,43 @@ describe('Test rename new devices', () => {
396
399
  ],
397
400
  })
398
401
  );
399
- expect(mockedDispatch).toBeCalledWith({
400
- payload: {
401
- index: 0,
402
- routes: [
403
- {
404
- name: 'Main',
405
- params: {
406
- params: { screen: 'Dashboard' },
407
- screen: 'DashboardStack',
408
- },
409
- },
410
- {
411
- name: 'UnitStack',
412
- params: {
413
- params: {
414
- isSuccessfullyConnected: true,
415
- routeName: 'DashboardStack',
416
- stationId: undefined,
417
- unitId: undefined,
418
- },
419
- screen: 'UnitDetail',
402
+ mockedDispatchNavigate();
403
+ });
404
+
405
+ it('onPressDone and goto detail not rename', async () => {
406
+ jest.useFakeTimers();
407
+ mock.onGet().reply(200, {
408
+ id: 1,
409
+ can_rename: true,
410
+ sensors: [
411
+ {
412
+ id: 1,
413
+ name: 'sensor',
414
+ end_devices: [
415
+ {
416
+ id: 1,
417
+ name: 'end_device',
420
418
  },
421
- },
422
- ],
423
- },
424
- type: 'RESET',
419
+ ],
420
+ },
421
+ ],
422
+ });
423
+
424
+ await act(async () => {
425
+ tree = await create(wrapComponent(route));
426
+ });
427
+ const instance = tree.root;
428
+ const doneButton = instance.find(
429
+ (el) =>
430
+ el.props.accessibilityLabel === AccessibilityLabel.BUTTON_DONE &&
431
+ el.type === TouchableOpacity
432
+ );
433
+ await act(async () => {
434
+ doneButton.props.onPress();
435
+ jest.advanceTimersByTime(3000);
425
436
  });
437
+
438
+ expect(mock.history.post).toHaveLength(0);
439
+ mockedDispatchNavigate();
426
440
  });
427
441
  });
@@ -27,12 +27,18 @@ const DetailConfigActionZigbee = () => {
27
27
  (isAction && itemActionConfig?.control_payload) ||
28
28
  '--',
29
29
  },
30
+ {
31
+ id: 2,
32
+ title: (isConfig && 'release_time') || '',
33
+ data: isConfig && itemActionConfig?.config?.release_time,
34
+ },
30
35
  ],
31
36
  [
32
37
  isAction,
33
38
  isConfig,
34
39
  itemActionConfig?.action?.name,
35
40
  itemActionConfig?.config?.name,
41
+ itemActionConfig?.config?.release_time,
36
42
  itemActionConfig?.control_payload,
37
43
  itemActionConfig?.key,
38
44
  ]
@@ -491,6 +491,7 @@ describe('test DeviceDetail', () => {
491
491
  standard: 'Temperature',
492
492
  measure: '°C',
493
493
  color: 'red',
494
+ unit: '°C',
494
495
  },
495
496
  ],
496
497
  },
@@ -419,7 +419,7 @@ const ScriptDetail = ({ route }) => {
419
419
  [AUTOMATE_TYPE.EVENT, AUTOMATE_TYPE.EVENT_ACTION].includes(type)
420
420
  ) {
421
421
  const { action, end_device_name, config_name, sensor_type, value } =
422
- automate?.event;
422
+ automate?.event || automate?.event_action || automate?.event_sensor;
423
423
  let textEvent = '';
424
424
  if (config_name) {
425
425
  const stateConditionData = STATE_VALUE_SENSOR_TYPES.find(
@@ -700,6 +700,7 @@
700
700
  "command_homeassistant_ready": "Home Assistant is connected",
701
701
  "command_homeassistant_lost": "Home Assistant is disconnection. Reconnecting...",
702
702
  "confirm": "Confirm",
703
+ "pick_a_date": "Pick a date",
703
704
  "car_validate_warning": "Please enter a right format of your license plate number \nEx:%{example}",
704
705
  "are_you_sure_this_resolved": "Are you sure this emergency situation has been resolved? All members in this unit will be notified.",
705
706
  "resolve_emergency": "Resolve",
@@ -1097,7 +1098,7 @@
1097
1098
  "no_zigbee_device_join_timeout": "No zigbee device join network after 2 minutes",
1098
1099
  "read_config_permission_error": "You don't have permission to read this config",
1099
1100
  "continue_to_wait": "Continue to wait?",
1100
- "it_has_been_5_minutes": "It has been 5 minutes...",
1101
+ "it_has_been_2_minutes": "It has been 2 minutes...",
1101
1102
  "click_here_to_setup_device": "Click here to setup device",
1102
1103
  "text_under_development": "This feature is under development.",
1103
1104
  "text_working_hard": "We are working hard to get this running",
@@ -1115,5 +1116,7 @@
1115
1116
  "config_type": "Config type",
1116
1117
  "pin": "PIN",
1117
1118
  "pin_mode": "PIN mode",
1119
+ "rename_device_fail": "Rename device fail",
1120
+ "release_time": "Release time",
1118
1121
  "data_address": "Data address"
1119
1122
  }
@@ -715,6 +715,7 @@
715
715
  "command_homeassistant_ready": "Home Assistant kết nối thành công",
716
716
  "command_homeassistant_lost": "Home Assistant bị mất kết nối. Đang kết nối lại...",
717
717
  "confirm": "Xác nhận",
718
+ "pick_a_date": "Chọn ngày",
718
719
  "car_validate_warning": "Vui lòng nhập đúng định dạng biển số xe \nVD: %{example}",
719
720
  "are_you_sure_this_resolved": "Bạn có chắc tình huống khẩn cấp này đã được xử lý xong? Các thành viên thuộc địa điểm này cũng sẽ nhận được thông báo.",
720
721
  "resolve_emergency": "Xử lý tình huống khẩn cấp",
@@ -1096,7 +1097,7 @@
1096
1097
  "no_zigbee_device_join_timeout": "Không có thiết bị zigbee nào được thêm vào sau 2 phút",
1097
1098
  "read_config_permission_error": "Bạn không có quyền đọc cấu hình này",
1098
1099
  "continue_to_wait": "Bạn có muốn đợi tiếp?",
1099
- "it_has_been_5_minutes": "Đã 5 phút trôi qua...",
1100
+ "it_has_been_2_minutes": "Đã 2 phút trôi qua...",
1100
1101
  "click_here_to_setup_device": "Chọn thiết bị thêm vào phòng",
1101
1102
  "text_alert_modal_popup_ct": "Đây là một hành động quan trọng và không thể hoàn tác.",
1102
1103
  "text_understand_modal_popup_ct": "Tôi hoàn toàn hiểu rằng hành động này là quan trọng và sẽ dẫn đến mất dữ liệu.",
@@ -1114,5 +1115,7 @@
1114
1115
  "config_type": "Loại cấu hình",
1115
1116
  "pin": "PIN",
1116
1117
  "pin_mode": "Chế độ mã PIN",
1118
+ "rename_device_fail": "Đổi tên thiết bị thất bại",
1119
+ "release_time": "Thời gian nhả trạng thái",
1117
1120
  "data_address": "Địa chỉ dữ liệu"
1118
1121
  }