@eohjsc/react-native-smart-city 0.3.56 → 0.3.58

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 (41) hide show
  1. package/package.json +3 -4
  2. package/src/commons/ActionGroup/ColorPickerTemplate.js +1 -1
  3. package/src/commons/ActionGroup/OnOffSmartLock/PasscodeList/__test__/index.test.js +11 -0
  4. package/src/commons/ActionGroup/SmartTiviActionTemplate/SmartTiviActionTemplate.js +0 -4
  5. package/src/commons/ActionGroup/SmartTiviActionTemplate/__test__/RectangleButton.test.js +13 -0
  6. package/src/commons/ActionGroup/__test__/ColorPickerTemplate.test.js +56 -3
  7. package/src/commons/ActionGroup/__test__/SliderRangeTemplate.test.js +18 -0
  8. package/src/commons/ActionTemplate/__test__/index.test.js +22 -0
  9. package/src/commons/Device/HorizontalBarChart.js +6 -0
  10. package/src/commons/Device/RainningSensor/CurrentRainSensor.js +1 -0
  11. package/src/commons/SubUnit/ShortDetail.js +1 -2
  12. package/src/commons/SubUnit/__test__/ShortDetail.test.js +1 -2
  13. package/src/screens/AddCommon/SelectUnit.js +1 -2
  14. package/src/screens/AddCommon/__test__/SelectUnit.test.js +4 -2
  15. package/src/screens/AddNewGateway/ConnectingDevice.js +2 -2
  16. package/src/screens/AddNewGateway/ConnectingModbusDevice.js +4 -4
  17. package/src/screens/AddNewGateway/ConnectingWifiDevice.js +10 -12
  18. package/src/screens/AddNewGateway/ConnectingWifiGuide.js +5 -5
  19. package/src/screens/AddNewGateway/ConnectingZigbeeDevice.js +4 -4
  20. package/src/screens/AddNewGateway/RenameNewDevices.js +4 -4
  21. package/src/screens/AddNewGateway/ScanGatewayQR.js +3 -3
  22. package/src/screens/AddNewGateway/ScanModbusQR.js +3 -3
  23. package/src/screens/AddNewGateway/ScanWifiDeviceQR.js +3 -3
  24. package/src/screens/AddNewGateway/SelectDeviceSubUnit.js +10 -13
  25. package/src/screens/AddNewGateway/SelectDeviceType.js +6 -9
  26. package/src/screens/AddNewGateway/SelectDeviceUnit.js +1 -2
  27. package/src/screens/AddNewGateway/SelectModbusGateway.js +6 -7
  28. package/src/screens/AddNewGateway/SelectZigbeeGateway.js +4 -4
  29. package/src/screens/AddNewGateway/ShareWifiPassword.js +5 -5
  30. package/src/screens/AddNewGateway/__test__/ConnectingWifiGuide.test.js +9 -9
  31. package/src/screens/AddNewGateway/__test__/ConnectingZigbeeDevice.test.js +6 -2
  32. package/src/screens/AddNewGateway/__test__/SelectModbusGateway.test.js +6 -2
  33. package/src/screens/AddNewGateway/__test__/SelectZigbeeGateway.test.js +6 -2
  34. package/src/screens/Device/components/SensorDisplayItem.js +2 -2
  35. package/src/screens/Device/hooks/useEvaluateValue.js +1 -1
  36. package/src/screens/SubUnit/Detail.js +1 -2
  37. package/src/screens/Template/detail.js +33 -2
  38. package/src/screens/Template/utils/ValueEvaluation.js +18 -0
  39. package/src/screens/Unit/AddMenu.js +1 -1
  40. package/src/utils/I18n/translations/en.json +1 -0
  41. package/src/utils/I18n/translations/vi.json +1 -0
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.56",
4
+ "version": "0.3.58",
5
5
  "description": "TODO",
6
6
  "main": "index.js",
7
7
  "files": [
@@ -65,8 +65,6 @@
65
65
  "licenseFilename": "LICENSE",
66
66
  "peerDependencies": {
67
67
  "@react-native-community/clipboard": "*",
68
- "lottie-ios": "*",
69
- "lottie-react-native": "*",
70
68
  "react": "*",
71
69
  "react-native": "*"
72
70
  },
@@ -138,6 +136,7 @@
138
136
  "i18n-js": "^3.7.1",
139
137
  "i18next": "^20.1.0",
140
138
  "lodash": "^4.17.19",
139
+ "lottie-react-native": "4.0.3",
141
140
  "moment": "^2.27.0",
142
141
  "moment-timezone": "^0.5.32",
143
142
  "numeral": "^2.0.6",
@@ -198,7 +197,7 @@
198
197
  "react-native-svg": "^12.1.0",
199
198
  "react-native-toast-message": "^2.1.1",
200
199
  "react-native-udp": "^4.1.3",
201
- "react-native-unimodules": "^0.11.0",
200
+ "react-native-unimodules": "0.14.8",
202
201
  "react-native-version-check": "^3.4.2",
203
202
  "react-native-vlc-media-player": "^1.0.41",
204
203
  "react-native-webview": "11.17.2",
@@ -13,7 +13,7 @@ import { SCContext } from '../../context';
13
13
  import { Action } from '../../context/actionType';
14
14
  import { DEVICE_TYPE } from '../../configs/Constants';
15
15
 
16
- const WheelColorPicker = ({ color, onChangeColorComplete, onStart }) => {
16
+ export const WheelColorPicker = ({ color, onChangeColorComplete, onStart }) => {
17
17
  const regex = /^#([0-9a-f]{3}){1,2}$/i;
18
18
  const isCheckHex = regex.test(color);
19
19
  // check crash if valueColor value wrong
@@ -6,6 +6,7 @@ import { AccessibilityLabel } from '../../../../../configs/Constants';
6
6
  import { SCProvider } from '../../../../../context';
7
7
  import PasscodeList from '../index';
8
8
  import { TouchableOpacity } from 'react-native';
9
+ import Routes from '../../../../../utils/Route';
9
10
 
10
11
  const mockNavigate = jest.fn();
11
12
  jest.mock('@react-navigation/native', () => {
@@ -43,5 +44,15 @@ describe('Test SetupGeneratePasscode', () => {
43
44
  );
44
45
 
45
46
  expect(passcode_list).toHaveLength(3);
47
+
48
+ await act(async () => {
49
+ await passcode_list[0].props.onPress();
50
+ });
51
+ expect(mockNavigate).toBeCalledWith(Routes.SmartLockStack, {
52
+ screen: Routes.ItemPasscode,
53
+ params: {
54
+ item: { code: 123361, name: 'Do Loi' },
55
+ },
56
+ });
46
57
  });
47
58
  });
@@ -70,8 +70,6 @@ const SmartTiviActionTemplate = memo(
70
70
  case SMART_TIVI_BUTTON.BACK_BUTTON:
71
71
  case SMART_TIVI_BUTTON.CHANNEL_BUTTON:
72
72
  return notImplemented(t);
73
- default:
74
- return <></>;
75
73
  }
76
74
  },
77
75
  [t]
@@ -86,8 +84,6 @@ const SmartTiviActionTemplate = memo(
86
84
  return <Netflix style={styles.iconChannel} />;
87
85
  case 'spotify':
88
86
  return <Spotify style={styles.iconChannel} />;
89
- default:
90
- return <></>;
91
87
  }
92
88
  }, []);
93
89
  return (
@@ -111,4 +111,17 @@ describe('Test RectangleButton', () => {
111
111
  RectangleButtonDown.props.onPress();
112
112
  });
113
113
  });
114
+
115
+ it('render type not handle', async () => {
116
+ type = 'not-handle';
117
+ const mockOnPress = jest.fn();
118
+ await act(async () => {
119
+ wrapper = await create(
120
+ wrapComponent(type, mockOnPress, mockOnPress, mockOnPress)
121
+ );
122
+ });
123
+ const instance = wrapper.root;
124
+ const touches = instance.findAllByType(TouchableOpacity);
125
+ expect(touches).toHaveLength(0);
126
+ });
114
127
  });
@@ -2,10 +2,22 @@ import { watchMultiConfigs } from '../../../iot/Monitor';
2
2
  import React from 'react';
3
3
  import { act, create } from 'react-test-renderer';
4
4
  import ColorPickerTemplate from '../ColorPickerTemplate';
5
+ import { WheelColorPicker } from '../ColorPickerTemplate';
5
6
  import { SCProvider } from '../../../context';
6
7
  import { mockSCStore } from '../../../context/mockStore';
7
8
  import { useConfigGlobalState } from '../../../iot/states';
8
9
  import ColorPicker from 'react-native-wheel-color-picker';
10
+ import { DEVICE_TYPE } from '../../../configs/Constants';
11
+
12
+ const mockSetAction = jest.fn();
13
+ jest.mock('react', () => {
14
+ return {
15
+ ...jest.requireActual('react'),
16
+ useContext: () => ({
17
+ setAction: mockSetAction,
18
+ }),
19
+ };
20
+ });
9
21
 
10
22
  jest.mock('../../../iot/Monitor');
11
23
  const mockDoAction = jest.fn();
@@ -46,6 +58,7 @@ describe('Test ColorPickerTemplate', () => {
46
58
  },
47
59
  title: '',
48
60
  };
61
+ mockSetAction.mockClear();
49
62
  });
50
63
 
51
64
  it('render template ColorPickerTemplate', async () => {
@@ -58,10 +71,50 @@ describe('Test ColorPickerTemplate', () => {
58
71
  wrapper = await create(wrapComponent(actionGroup, mockDoAction, sensor));
59
72
  });
60
73
  const instance = wrapper.root;
61
- const picker = instance.findAllByType(ColorPicker);
62
- expect(picker).toHaveLength(1);
74
+ const pickers = instance.findAllByType(ColorPicker);
75
+ expect(pickers).toHaveLength(1);
76
+ expect(pickers[0].props.color).toEqual('#ffffff');
77
+ await act(async () => {
78
+ await pickers[0].props.onColorChangeComplete();
79
+ });
80
+ });
81
+
82
+ it('render template ColorPickerTemplate config value not null', async () => {
83
+ useConfigGlobalState.mockImplementation(() => [
84
+ {
85
+ 5: {
86
+ value: 3093151,
87
+ },
88
+ },
89
+ jest.fn(),
90
+ ]);
91
+ const sensor = {
92
+ is_managed_by_backend: true,
93
+ name: 'Sensor',
94
+ device_type: DEVICE_TYPE.LG_THINQ,
95
+ };
96
+ await act(async () => {
97
+ wrapper = await create(wrapComponent(actionGroup, mockDoAction, sensor));
98
+ });
99
+ const instance = wrapper.root;
100
+ const pickers = instance.findAllByType(ColorPicker);
101
+ expect(pickers[0].props.color).toEqual(`#${3093151?.toString(16)}`);
102
+ });
103
+
104
+ it('test WheelColorPicker onStartPick set global state lock view', async () => {
105
+ const sensor = {
106
+ is_managed_by_backend: true,
107
+ name: 'Sensor',
108
+ device_type: DEVICE_TYPE.LG_THINQ,
109
+ };
110
+ await act(async () => {
111
+ wrapper = await create(wrapComponent(actionGroup, mockDoAction, sensor));
112
+ });
113
+ const instance = wrapper.root;
114
+ const wheelpicker = instance.findByType(WheelColorPicker);
63
115
  await act(async () => {
64
- await picker[0].props.onColorChangeComplete();
116
+ await wheelpicker.props.onStart();
65
117
  });
118
+ expect(mockSetAction).toBeCalled();
66
119
  });
67
120
  });
@@ -85,4 +85,22 @@ describe('Test SliderRangeTemplate', () => {
85
85
  JSON.stringify({ value_brness: 50 })
86
86
  );
87
87
  });
88
+
89
+ it('render template SliderRangeTemplate with config value not null', async () => {
90
+ useConfigGlobalState.mockImplementation(() => [
91
+ {
92
+ 5: {
93
+ value: 50,
94
+ },
95
+ },
96
+ jest.fn(),
97
+ ]);
98
+ const sensor = { is_managed_by_backend: true, name: 'Sensor' };
99
+ await act(async () => {
100
+ wrapper = await create(wrapComponent(actionGroup, mockDoAction, sensor));
101
+ });
102
+ const instance = wrapper.root;
103
+ const silderRange = instance.findByType(SliderRange);
104
+ expect(silderRange.props.value).toBe(50);
105
+ });
88
106
  });
@@ -62,6 +62,28 @@ describe('Test ActionTemplate', () => {
62
62
  action_off: '94ae262d-46e3-42ff-9d10-516831ecc830',
63
63
  },
64
64
  },
65
+ {
66
+ title: '',
67
+ template: 'curtain_action_template',
68
+ configuration: {
69
+ open_action: '94ae262d-46e3-42ff-9d10-516831ecc830',
70
+ close_action: '94ae262d-46e3-42ff-9d10-516831ecc830',
71
+ stop_action: '94ae262d-46e3-42ff-9d10-516831ecc830',
72
+ text1: 'One',
73
+ text2: 'Two',
74
+ text3: 'Three',
75
+ },
76
+ },
77
+ {
78
+ title: '',
79
+ template: 'OnOffSmartLockActionTemplate',
80
+ configuration: {
81
+ action_on: '94ae262d-46e3-42ff-9d10-516831ecc830',
82
+ action_off: '94ae262d-46e3-42ff-9d10-516831ecc830',
83
+ text_on: 'on',
84
+ text_off: 'off',
85
+ },
86
+ },
65
87
  ];
66
88
  it('test onPress SelectActionCard', async () => {
67
89
  await act(async () => {
@@ -126,6 +126,8 @@ const HorizontalBarChart = memo(({ datas, config }) => {
126
126
  dataY.splice(maxY._index, 1, { ...maxY.max, color: Colors.Primary });
127
127
  }
128
128
 
129
+ const isAllZero = dataY.every((item) => item.y === 0);
130
+
129
131
  setChartOptions((options) => ({
130
132
  ...options,
131
133
  chart: {
@@ -135,6 +137,10 @@ const HorizontalBarChart = memo(({ datas, config }) => {
135
137
  ...options.xAxis,
136
138
  categories: dataX,
137
139
  },
140
+ yAxis: {
141
+ ...options.yAxis,
142
+ minRange: isAllZero ? 0.5 : 0,
143
+ },
138
144
  series: [
139
145
  {
140
146
  name: JSON.stringify(config),
@@ -17,6 +17,7 @@ const CurrentRainSensor = memo(({ data = [] }) => {
17
17
  const { text, raining, backgroundColor, borderColor } = item.evaluate
18
18
  ? item.evaluate
19
19
  : {};
20
+
20
21
  return (
21
22
  <View style={styles.standard}>
22
23
  <CircleView
@@ -102,8 +102,7 @@ const ShortDetailSubUnit = ({ unit, station, isOwner }) => {
102
102
  navigate(Routes.AddGatewayStack, {
103
103
  screen: Routes.SelectDeviceType,
104
104
  params: {
105
- unitId: unit?.id,
106
- unitName: unit?.name,
105
+ unit,
107
106
  subUnit: station,
108
107
  },
109
108
  });
@@ -167,8 +167,7 @@ describe('test ShortDetail Subunit', () => {
167
167
  expect(mockedNavigate).toHaveBeenCalledWith(Routes.AddGatewayStack, {
168
168
  screen: Routes.SelectDeviceType,
169
169
  params: {
170
- unitId: props.unit.id,
171
- unitName: props.unit.name,
170
+ unit: props.unit,
172
171
  subUnit: props.station,
173
172
  },
174
173
  });
@@ -51,8 +51,7 @@ const AddCommonSelectUnit = ({ route }) => {
51
51
  navigation.navigate(Routes.AddGatewayStack, {
52
52
  screen: Routes.SelectDeviceType,
53
53
  params: {
54
- unitId: unit?.id,
55
- unitName: unit?.name,
54
+ unit,
56
55
  },
57
56
  });
58
57
  break;
@@ -123,8 +123,10 @@ describe('Test SelectUnit container', () => {
123
123
  expect(mockedNavigate).toBeCalledWith('AddGatewayStack', {
124
124
  screen: 'SelectDeviceType',
125
125
  params: {
126
- unitId: 1,
127
- unitName: 'Unit 1',
126
+ unit: {
127
+ id: 1,
128
+ name: 'Unit 1',
129
+ },
128
130
  },
129
131
  });
130
132
  break;
@@ -12,7 +12,7 @@ const ConnectingDevice = ({
12
12
  fail,
13
13
  initState,
14
14
  onReady,
15
- unitId,
15
+ unit,
16
16
  subUnit,
17
17
  chipId,
18
18
  sensorId,
@@ -26,7 +26,7 @@ const ConnectingDevice = ({
26
26
  const { navigate, goBack } = useNavigation();
27
27
 
28
28
  const [renameParams, setRenameParams] = useState({
29
- unitId,
29
+ unit,
30
30
  subUnit,
31
31
  chipId,
32
32
  sensorId,
@@ -9,7 +9,7 @@ import ConnectingDevice from './ConnectingDevice';
9
9
 
10
10
  const ConnectingModbusDevice = ({ route }) => {
11
11
  const t = useTranslations();
12
- const { unitId, subUnit, chipId, qrData } = route?.params || {};
12
+ const { unit, subUnit, chipId, qrData } = route?.params || {};
13
13
  const [sensorId, setSensorId] = useState(null);
14
14
  const [channelNameTemp, setChannelNameTemp] = useState('');
15
15
  const [isChangeAddressSuccess, setIsChangeAddressSuccess] = useState(false);
@@ -27,7 +27,7 @@ const ConnectingModbusDevice = ({ route }) => {
27
27
  setChannelNameTemp(channelName);
28
28
  const { success, data } = await axiosPost(API.CHIP.SCAN_SENSOR(chipId), {
29
29
  imei: qrData.imei,
30
- unit: unitId,
30
+ unit: unit?.id,
31
31
  station: subUnit?.id,
32
32
  channel_name: channelName,
33
33
  });
@@ -36,7 +36,7 @@ const ConnectingModbusDevice = ({ route }) => {
36
36
  }
37
37
  setSensorId(data.id);
38
38
  },
39
- [chipId, qrData, subUnit, unitId]
39
+ [chipId, qrData, subUnit, unit]
40
40
  );
41
41
 
42
42
  useEffect(() => {
@@ -66,7 +66,7 @@ const ConnectingModbusDevice = ({ route }) => {
66
66
  title={t('connect_device')}
67
67
  initState={t('connecting_to_gateway')}
68
68
  onReady={onReady}
69
- unitId={unitId}
69
+ unit={unit}
70
70
  subUnit={subUnit}
71
71
  chipId={chipId}
72
72
  sensorId={sensorId}
@@ -12,7 +12,7 @@ let isCallingAPI = false;
12
12
 
13
13
  const ConnectingWifiDevice = ({ route }) => {
14
14
  const t = useTranslations();
15
- const { unitId, subUnit, gateway, selectedWifi, qrData, addDeviceType } =
15
+ const { unit, subUnit, gateway, selectedWifi, qrData, addDeviceType } =
16
16
  route?.params || {};
17
17
  const { goBack } = useNavigation();
18
18
 
@@ -38,7 +38,7 @@ const ConnectingWifiDevice = ({ route }) => {
38
38
  isCallingAPI = true;
39
39
  const timeout = setTimeout(async () => {
40
40
  const { success, problem, data } = await axiosPost(
41
- API.UNIT.CHIP_SCAN(unitId),
41
+ API.UNIT.CHIP_SCAN(unit?.id),
42
42
  {
43
43
  imei: gateway?.imei,
44
44
  secret: qrData?.secret,
@@ -60,22 +60,20 @@ const ConnectingWifiDevice = ({ route }) => {
60
60
  }
61
61
  },
62
62
  [
63
- gateway,
64
- selectedWifi,
65
- unitId,
63
+ unit?.id,
64
+ gateway?.imei,
65
+ gateway?.model,
66
66
  qrData?.secret,
67
- subUnit,
67
+ subUnit?.id,
68
+ selectedWifi.ssid,
69
+ selectedWifi.password,
68
70
  addingWifiDeviceFail,
69
71
  ]
70
72
  );
71
73
 
72
74
  useEffect(() => {
73
75
  const unsubscribe = NetInfo.addEventListener((state) => {
74
- if (
75
- state.isConnected &&
76
- state.details?.ssid === selectedWifi.ssid &&
77
- channelName
78
- ) {
76
+ if (state.isConnected && channelName) {
79
77
  onReady(channelName);
80
78
  }
81
79
  });
@@ -89,7 +87,7 @@ const ConnectingWifiDevice = ({ route }) => {
89
87
  fail={addingWifiDeviceFail}
90
88
  initState={t('connecting_to_device')}
91
89
  onReady={setChannelName}
92
- unitId={unitId}
90
+ unit={unit}
93
91
  subUnit={subUnit}
94
92
  chipId={chipId}
95
93
  addDeviceType={addDeviceType}
@@ -25,7 +25,7 @@ const ConnectingWifiGuide = ({ route }) => {
25
25
  const t = useTranslations();
26
26
  const {
27
27
  qrData,
28
- unitId,
28
+ unit,
29
29
  subUnit,
30
30
  addDeviceType,
31
31
  stationId,
@@ -53,7 +53,7 @@ const ConnectingWifiGuide = ({ route }) => {
53
53
  },
54
54
  {
55
55
  text: t('retry'),
56
- onPress: connectToDeviceWifi,
56
+ onPress: () => connectToDeviceWifi(),
57
57
  },
58
58
  ],
59
59
  [connectToDeviceWifi, goBack, t]
@@ -104,7 +104,7 @@ const ConnectingWifiGuide = ({ route }) => {
104
104
  if (!wifi) {
105
105
  phoneWifiList = null;
106
106
  Alert.alert(
107
- t('fail_to_discover_device_wifi'),
107
+ t('cannot_find_device_wifi'),
108
108
  t('try_to_turn_on_device_or_try_again'),
109
109
  buttons
110
110
  );
@@ -173,7 +173,7 @@ const ConnectingWifiGuide = ({ route }) => {
173
173
  socket?.close();
174
174
  socket = null;
175
175
  navigate(Routes.ShareWifiPassword, {
176
- unitId,
176
+ unit,
177
177
  subUnit,
178
178
  wifiList,
179
179
  qrData: qrData,
@@ -181,7 +181,7 @@ const ConnectingWifiGuide = ({ route }) => {
181
181
  stationId,
182
182
  });
183
183
  }
184
- }, [addDeviceType, navigate, qrData, stationId, subUnit, unitId, wifiList]);
184
+ }, [addDeviceType, navigate, qrData, stationId, subUnit, unit, wifiList]);
185
185
 
186
186
  return (
187
187
  <View style={styles.container}>
@@ -10,7 +10,7 @@ import ConnectingDevice from './ConnectingDevice';
10
10
  const ConnectingZigbeeDevice = ({ route }) => {
11
11
  const t = useTranslations();
12
12
  const { goBack } = useNavigation();
13
- const { unitId, subUnit, chipId } = route?.params || {};
13
+ const { unit, subUnit, chipId } = route?.params || {};
14
14
 
15
15
  const fail = useCallback(
16
16
  (message) => {
@@ -31,7 +31,7 @@ const ConnectingZigbeeDevice = ({ route }) => {
31
31
  {
32
32
  channel_name: channelName,
33
33
  station: subUnit?.id,
34
- unit: unitId,
34
+ unit: unit?.id,
35
35
  }
36
36
  );
37
37
 
@@ -40,7 +40,7 @@ const ConnectingZigbeeDevice = ({ route }) => {
40
40
  return;
41
41
  }
42
42
  },
43
- [chipId, fail, subUnit?.id, unitId]
43
+ [chipId, fail, subUnit?.id, unit?.id]
44
44
  );
45
45
 
46
46
  return (
@@ -49,7 +49,7 @@ const ConnectingZigbeeDevice = ({ route }) => {
49
49
  fail={fail}
50
50
  initState={t('connecting_to_gateway')}
51
51
  onReady={onReady}
52
- unitId={unitId}
52
+ unit={unit}
53
53
  subUnit={subUnit}
54
54
  chipId={chipId}
55
55
  sensorId={null}
@@ -20,7 +20,7 @@ const RenameNewDevices = memo(({ route }) => {
20
20
  const t = useTranslations();
21
21
  const { dispatch } = useNavigation();
22
22
 
23
- const { unitId, subUnit, chipId, sensorId, addDeviceType } =
23
+ const { unit, subUnit, chipId, sensorId, addDeviceType } =
24
24
  route?.params || {};
25
25
  const [selectedItem, setSelectedItem] = useState({});
26
26
  const [isCanRename, setIsCanRename] = useState(false);
@@ -68,7 +68,7 @@ const RenameNewDevices = memo(({ route }) => {
68
68
  params: {
69
69
  screen: Routes.UnitDetail,
70
70
  params: {
71
- unitId: unitId,
71
+ unitId: unit?.id,
72
72
  stationId: subUnit?.id,
73
73
  isSuccessfullyConnected: true,
74
74
  routeName: Routes.DashboardStack,
@@ -78,7 +78,7 @@ const RenameNewDevices = memo(({ route }) => {
78
78
  ],
79
79
  });
80
80
  dispatch(resetAction);
81
- }, [dispatch, info, subUnit?.id, unitId]);
81
+ }, [dispatch, info, subUnit?.id, unit?.id]);
82
82
 
83
83
  useEffect(() => {
84
84
  (async () => {
@@ -244,7 +244,7 @@ const RenameNewDevices = memo(({ route }) => {
244
244
  {t('successfully_connected')}
245
245
  </Text>
246
246
  <Text size={14} color={Colors.Gray9}>
247
- {subUnit?.name}
247
+ {[unit?.name, subUnit?.name].filter(Boolean).join(' - ')}
248
248
  </Text>
249
249
  {renderListItem}
250
250
  <Text size={16} color={Colors.Gray8} style={styles.textRename}>
@@ -8,7 +8,7 @@ import InvalidQRCode from '../ScanChipQR/components/InvalidQRCode';
8
8
 
9
9
  const ScanGatewayQR = memo(({ route }) => {
10
10
  // same as Scan Wifi Device, not sure if we should separated it
11
- const { unitId, stationId } = route?.params || {};
11
+ const { unit, stationId } = route?.params || {};
12
12
  const [isInvalidQrCode, setIsInvalidQrCode] = useState(false);
13
13
  const { navigate, goBack } = useNavigation();
14
14
 
@@ -28,14 +28,14 @@ const ScanGatewayQR = memo(({ route }) => {
28
28
  return;
29
29
  }
30
30
  navigate(Routes.ConnectingWifiGuide, {
31
- unitId,
31
+ unit,
32
32
  stationId,
33
33
  qrData: data,
34
34
  addDeviceType: 'gateway',
35
35
  });
36
36
  setLoading(true);
37
37
  },
38
- [navigate, stationId, unitId]
38
+ [navigate, stationId, unit]
39
39
  );
40
40
 
41
41
  const onRetry = useCallback(() => {
@@ -14,7 +14,7 @@ import { Colors } from '../../configs';
14
14
 
15
15
  const ScanModbusQR = memo(({ route }) => {
16
16
  const t = useTranslations();
17
- const { unitId, subUnit } = route?.params || {};
17
+ const { unit, subUnit } = route?.params || {};
18
18
  const { navigate, goBack } = useNavigation();
19
19
  const [showPopupGuide, setShowPopupGuide, setHidePopupGuide] = useBoolean();
20
20
  const [isInvalidQrCode, setIsInvalidQrCode] = useState(false);
@@ -36,12 +36,12 @@ const ScanModbusQR = memo(({ route }) => {
36
36
  return;
37
37
  }
38
38
  navigate(Routes.SelectModbusGateway, {
39
- unitId,
39
+ unit,
40
40
  subUnit,
41
41
  qrData: data,
42
42
  });
43
43
  },
44
- [navigate, unitId, subUnit]
44
+ [navigate, unit, subUnit]
45
45
  );
46
46
 
47
47
  const handleCancel = useCallback(() => {
@@ -6,7 +6,7 @@ import { useNavigation } from '@react-navigation/native';
6
6
  import InvalidQRCode from '../ScanChipQR/components/InvalidQRCode';
7
7
 
8
8
  const ScanWifiDeviceQR = memo(({ route }) => {
9
- const { unitId, subUnit } = route?.params || {};
9
+ const { unit, subUnit } = route?.params || {};
10
10
  const [isInvalidQrCode, setIsInvalidQrCode] = useState(false);
11
11
  const { navigate, goBack } = useNavigation();
12
12
 
@@ -26,13 +26,13 @@ const ScanWifiDeviceQR = memo(({ route }) => {
26
26
  return;
27
27
  }
28
28
  navigate(Routes.ConnectingWifiGuide, {
29
- unitId,
29
+ unit,
30
30
  subUnit,
31
31
  qrData: data,
32
32
  });
33
33
  setLoading(true);
34
34
  },
35
- [navigate, unitId, subUnit]
35
+ [navigate, subUnit, unit]
36
36
  );
37
37
 
38
38
  const onRetry = useCallback(() => {
@@ -7,40 +7,37 @@ import Routes from '../../utils/Route';
7
7
  import { DEVICE_TYPE } from '../../configs/Constants';
8
8
 
9
9
  const SelectDeviceSubUnit = ({ route }) => {
10
- const { unitId, unitName, deviceType } = route?.params || {};
10
+ const { unit, deviceType } = route?.params || {};
11
11
  const t = useTranslations();
12
12
  const navigation = useNavigation();
13
13
  const onPressNext = useCallback(
14
- (unit, subUnit) => {
14
+ (chosenUnit, chosenSubUnit) => {
15
15
  switch (deviceType) {
16
16
  case DEVICE_TYPE.WIFI_DEVICE:
17
17
  navigation.navigate(Routes.ScanWifiDeviceQR, {
18
- unitId,
19
- unitName,
20
- subUnit,
18
+ unit,
19
+ chosenSubUnit,
21
20
  });
22
21
  break;
23
22
  case DEVICE_TYPE.MODBUS:
24
23
  navigation.navigate(Routes.ScanModbusQR, {
25
- unitId,
26
- unitName,
27
- subUnit,
24
+ unit,
25
+ chosenSubUnit,
28
26
  });
29
27
  break;
30
28
  case DEVICE_TYPE.ZIGBEE:
31
29
  navigation.navigate(Routes.ConnectRouterGuide, {
32
- unitId,
33
- unitName,
34
- subUnit,
30
+ unit,
31
+ chosenSubUnit,
35
32
  });
36
33
  break;
37
34
  }
38
35
  },
39
- [deviceType, navigation, unitId, unitName]
36
+ [deviceType, navigation, unit]
40
37
  );
41
38
  return (
42
39
  <SelectSubUnit
43
- unitId={unitId}
40
+ unitId={unit?.id}
44
41
  title={t('text_select_sub_unit')}
45
42
  subTitle={t('select_a_sub_unit_want_add_device')}
46
43
  onPressNext={onPressNext}
@@ -53,7 +53,7 @@ const SelectDeviceGrid = ({ options, onSelect }) => {
53
53
 
54
54
  const SelectDeviceType = ({ route }) => {
55
55
  const t = useTranslations();
56
- const { unitId, unitName, subUnit } = route?.params || {};
56
+ const { unit, subUnit } = route?.params || {};
57
57
  const { navigate, goBack } = useNavigation();
58
58
  const [addType, setAddType] = useState();
59
59
  const [selectedAddType, setSelectedAddType] = useState();
@@ -65,7 +65,7 @@ const SelectDeviceType = ({ route }) => {
65
65
  image: <AddGatewayIcon width={60} height={60} />,
66
66
  route: Routes.ScanGatewayQR,
67
67
  data: {
68
- unitId,
68
+ unit,
69
69
  },
70
70
  title: t('gateway'),
71
71
  subtitle: t('central_controller'),
@@ -77,8 +77,7 @@ const SelectDeviceType = ({ route }) => {
77
77
  ? Routes.ScanWifiDeviceQR
78
78
  : Routes.SelectDeviceSubUnit,
79
79
  data: {
80
- unitId,
81
- unitName,
80
+ unit,
82
81
  subUnit,
83
82
  deviceType: DEVICE_TYPE.WIFI_DEVICE,
84
83
  },
@@ -90,8 +89,7 @@ const SelectDeviceType = ({ route }) => {
90
89
  image: <AddModbusDeviceIcon width={60} height={60} />,
91
90
  route: subUnit?.id ? Routes.ScanModbusQR : Routes.SelectDeviceSubUnit,
92
91
  data: {
93
- unitId,
94
- unitName,
92
+ unit,
95
93
  subUnit,
96
94
  deviceType: DEVICE_TYPE.MODBUS,
97
95
  },
@@ -105,8 +103,7 @@ const SelectDeviceType = ({ route }) => {
105
103
  ? Routes.ConnectRouterGuide
106
104
  : Routes.SelectDeviceSubUnit,
107
105
  data: {
108
- unitId,
109
- unitName,
106
+ unit,
110
107
  subUnit,
111
108
  deviceType: DEVICE_TYPE.ZIGBEE,
112
109
  },
@@ -118,7 +115,7 @@ const SelectDeviceType = ({ route }) => {
118
115
  list.shift();
119
116
  }
120
117
  return list;
121
- }, [t, unitId, unitName, subUnit]);
118
+ }, [unit, t, subUnit]);
122
119
 
123
120
  const onRight = useCallback(() => {
124
121
  if (selectedAddType?.route && selectedAddType?.data) {
@@ -10,8 +10,7 @@ const SelectDeviceUnit = ({ route }) => {
10
10
  const onPressNext = useCallback(
11
11
  (unit) => {
12
12
  navigate(Routes.SelectDeviceType, {
13
- unitId: unit?.id,
14
- unitName: unit?.name,
13
+ unit,
15
14
  });
16
15
  },
17
16
  [navigate]
@@ -7,29 +7,28 @@ import Routes from '../../utils/Route';
7
7
  const SelectModbusGateway = ({ route }) => {
8
8
  const t = useTranslations();
9
9
  const navigation = useNavigation();
10
- const { unitId, unitName, subUnit, qrData } = route?.params || {};
10
+ const { unit, subUnit, qrData } = route?.params || {};
11
11
 
12
12
  const onPressNext = useCallback(
13
13
  (gateway) => {
14
14
  navigation.navigate(Routes.ConnectingModbusDevice, {
15
- unitId,
15
+ unit,
16
16
  subUnit,
17
17
  chipId: gateway.id,
18
18
  qrData,
19
19
  });
20
20
  },
21
- [navigation, unitId, subUnit, qrData]
21
+ [navigation, unit, subUnit, qrData]
22
22
  );
23
23
 
24
24
  const onPressOk = useCallback(
25
25
  (gateway) => {
26
26
  navigation.navigate(Routes.SelectDeviceType, {
27
- unitId,
28
- unitName,
27
+ unit,
29
28
  subUnit,
30
29
  });
31
30
  },
32
- [navigation, subUnit, unitId, unitName]
31
+ [navigation, subUnit, unit]
33
32
  );
34
33
 
35
34
  return (
@@ -38,7 +37,7 @@ const SelectModbusGateway = ({ route }) => {
38
37
  onPressOk={onPressOk}
39
38
  title={t('text_select_a_gateway')}
40
39
  subTitle={t('text_select_a_gateway')}
41
- unitId={unitId}
40
+ unitId={unit?.id}
42
41
  type="modbus"
43
42
  />
44
43
  );
@@ -7,18 +7,18 @@ import Routes from '../../utils/Route';
7
7
  const SelectZigbeeGateway = ({ route }) => {
8
8
  const t = useTranslations();
9
9
  const { navigate } = useNavigation();
10
- const { unitId, subUnit } = route?.params || {};
10
+ const { unit, subUnit } = route?.params || {};
11
11
 
12
12
  const onPressNext = useCallback(
13
13
  (gateway) => {
14
14
  gateway &&
15
15
  navigate(Routes.ZigbeeDeviceConnectGuide, {
16
- unitId,
16
+ unit,
17
17
  subUnit,
18
18
  chipId: gateway.id,
19
19
  });
20
20
  },
21
- [unitId, subUnit, navigate]
21
+ [unit, subUnit, navigate]
22
22
  );
23
23
 
24
24
  return (
@@ -26,7 +26,7 @@ const SelectZigbeeGateway = ({ route }) => {
26
26
  onPressNext={onPressNext}
27
27
  title={t('text_select_a_gateway')}
28
28
  subTitle={t('text_select_a_gateway')}
29
- unitId={unitId}
29
+ unitId={unit?.id}
30
30
  type="zigbee"
31
31
  />
32
32
  );
@@ -54,7 +54,7 @@ const WifiItem = ({ item, setIsShowPopupPassword, setSelectedWifi }) => {
54
54
  };
55
55
 
56
56
  const ShareWifiPassword = ({ route }) => {
57
- const { wifiList, unitId, subUnit, qrData, addDeviceType, stationId } =
57
+ const { wifiList, unit, subUnit, qrData, addDeviceType, stationId } =
58
58
  route?.params || {};
59
59
  const t = useTranslations();
60
60
  const { navigate } = useNavigation();
@@ -157,14 +157,14 @@ const ShareWifiPassword = ({ route }) => {
157
157
  socket = null;
158
158
  }
159
159
  navigate(Routes.ConnectingWifiGuide, {
160
- unitId,
160
+ unit,
161
161
  stationId,
162
162
  subUnit,
163
163
  qrData,
164
164
  addDeviceType,
165
165
  isBackFromOtherScreen: true,
166
166
  });
167
- }, [addDeviceType, navigate, qrData, stationId, subUnit, unitId]);
167
+ }, [addDeviceType, navigate, qrData, stationId, subUnit, unit]);
168
168
 
169
169
  useEffect(() => {
170
170
  let checkWifiInterval;
@@ -189,7 +189,7 @@ const ShareWifiPassword = ({ route }) => {
189
189
  socket?.close();
190
190
  socket = null;
191
191
  navigate(Routes.ConnectingWifiDevice, {
192
- unitId,
192
+ unit,
193
193
  subUnit,
194
194
  gateway: dataGateway.gateway[0],
195
195
  qrData: qrData,
@@ -225,8 +225,8 @@ const ShareWifiPassword = ({ route }) => {
225
225
  stationId,
226
226
  subUnit,
227
227
  t,
228
- unitId,
229
228
  wifiList,
229
+ unit,
230
230
  ]);
231
231
 
232
232
  return (
@@ -138,9 +138,7 @@ describe('test share wifi password', () => {
138
138
  tree = await renderer.create(wrapComponent(route));
139
139
  });
140
140
  await ConnectWifiActionButton(tree.root);
141
- expect(Alert.alert.mock.calls[0][0]).toEqual(
142
- 'Fail to discover device wifi'
143
- );
141
+ expect(Alert.alert.mock.calls[0][0]).toEqual("Cannot find Device's Wifi");
144
142
  expect(Alert.alert.mock.calls[0][1]).toEqual(
145
143
  'Try to turn on device or Try again'
146
144
  );
@@ -153,7 +151,7 @@ describe('test share wifi password', () => {
153
151
  it('fail connect to wifi android show error push retry', async () => {
154
152
  jest.spyOn(Alert, 'alert');
155
153
  Alert.alert(
156
- 'Fail to discover device wifi',
154
+ "Cannot find Device's Wifi",
157
155
  'Try to turn on device or Try again',
158
156
  [
159
157
  { text: 'Cancel', onPress: mockedGoBack },
@@ -175,9 +173,7 @@ describe('test share wifi password', () => {
175
173
  tree = await renderer.create(wrapComponent(route));
176
174
  });
177
175
  await ConnectWifiActionButton(tree.root);
178
- expect(Alert.alert.mock.calls[1][0]).toEqual(
179
- 'Fail to discover device wifi'
180
- );
176
+ expect(Alert.alert.mock.calls[1][0]).toEqual("Cannot find Device's Wifi");
181
177
  expect(Alert.alert.mock.calls[1][1]).toEqual(
182
178
  'Try to turn on device or Try again'
183
179
  );
@@ -222,7 +218,9 @@ describe('test share wifi password', () => {
222
218
  const route = {
223
219
  params: {
224
220
  qrData: { org_slug: 'eoh', prefix: 'robot' },
225
- unitId: 1,
221
+ unit: {
222
+ id: 1,
223
+ },
226
224
  subUnit: {
227
225
  id: 1,
228
226
  },
@@ -248,7 +246,9 @@ describe('test share wifi password', () => {
248
246
  expect(socket.close).toBeCalled();
249
247
 
250
248
  expect(mockedNavigate).toBeCalledWith('ShareWifiPassword', {
251
- unitId: 1,
249
+ unit: {
250
+ id: 1,
251
+ },
252
252
  subUnit: {
253
253
  id: 1,
254
254
  },
@@ -55,7 +55,9 @@ describe('Test connecting modbus device', () => {
55
55
  beforeEach(() => {
56
56
  route = {
57
57
  params: {
58
- unitId: 1,
58
+ unit: {
59
+ id: 1,
60
+ },
59
61
  subUnit: {
60
62
  id: 2,
61
63
  station: 'Station 2',
@@ -108,7 +110,9 @@ describe('Test connecting modbus device', () => {
108
110
  });
109
111
  expect(mockedNavigate).toHaveBeenCalledWith(Routes.RenameNewDevices, {
110
112
  addDeviceType: undefined,
111
- unitId: 1,
113
+ unit: {
114
+ id: 1,
115
+ },
112
116
  subUnit: {
113
117
  id: 2,
114
118
  station: 'Station 2',
@@ -38,7 +38,9 @@ describe('Test select modbus gateway', () => {
38
38
  beforeEach(() => {
39
39
  route = {
40
40
  params: {
41
- unitId: 1,
41
+ unit: {
42
+ id: 1,
43
+ },
42
44
  subUnit: {
43
45
  id: 2,
44
46
  },
@@ -67,7 +69,9 @@ describe('Test select modbus gateway', () => {
67
69
  });
68
70
 
69
71
  expect(mockedNavigate).toBeCalledWith(Routes.ConnectingModbusDevice, {
70
- unitId: 1,
72
+ unit: {
73
+ id: 1,
74
+ },
71
75
  subUnit: {
72
76
  id: 2,
73
77
  },
@@ -38,7 +38,9 @@ describe('Test select zigbee gateway', () => {
38
38
  beforeEach(() => {
39
39
  route = {
40
40
  params: {
41
- unitId: 1,
41
+ unit: {
42
+ id: 1,
43
+ },
42
44
  subUnit: {
43
45
  id: 2,
44
46
  },
@@ -67,7 +69,9 @@ describe('Test select zigbee gateway', () => {
67
69
  });
68
70
 
69
71
  expect(mockedNavigate).toBeCalledWith(Routes.ZigbeeDeviceConnectGuide, {
70
- unitId: 1,
72
+ unit: {
73
+ id: 1,
74
+ },
71
75
  subUnit: {
72
76
  id: 2,
73
77
  },
@@ -41,7 +41,7 @@ export const SensorDisplayItem = ({
41
41
  const t = useTranslations();
42
42
  const userId = useSCContextSelector((state) => state.auth.account.user.id);
43
43
  const { configuration = {}, id: idTemplate } = item;
44
- const { type, uri, id, name, title } = configuration;
44
+ const { type, template, uri, id, name, title } = configuration;
45
45
 
46
46
  const { isEditingTemplate } = useSCContextSelector((state) => state.devMode);
47
47
 
@@ -94,7 +94,7 @@ export const SensorDisplayItem = ({
94
94
  case 'history':
95
95
  return <DetailHistoryChart item={item} sensor={sensor} />;
96
96
  case 'value':
97
- switch (type) {
97
+ switch (type || template) {
98
98
  case 'circle':
99
99
  return (
100
100
  <CardDevMode id={idTemplate}>
@@ -56,7 +56,7 @@ const evaluateBoolean = (value, configuration) => {
56
56
  return { text: value };
57
57
  };
58
58
 
59
- const valueEvaluationFuncs = {
59
+ export const valueEvaluationFuncs = {
60
60
  range: evaluateRange,
61
61
  boolean: evaluateBoolean,
62
62
  };
@@ -78,8 +78,7 @@ const SubUnitDetail = ({ route }) => {
78
78
  params: {
79
79
  stationName: station.name,
80
80
  stationId: station.id,
81
- unitId: unit.id,
82
- unitName: unit.name,
81
+ unit,
83
82
  },
84
83
  });
85
84
  }, [navigation, station, unit]);
@@ -20,6 +20,8 @@ import Routes from '../../utils/Route';
20
20
  import { SensorDisplayItem } from '../Device/components/SensorDisplayItem';
21
21
  import { axiosGet } from '../../utils/Apis/axios';
22
22
  import { watchMultiConfigs } from '../../iot/Monitor';
23
+ import { useConfigGlobalState } from '../../iot/states';
24
+ import { evaluateValue } from './utils/ValueEvaluation';
23
25
 
24
26
  const TemplateDetail = () => {
25
27
  const refMenuAction = useRef();
@@ -31,6 +33,9 @@ const TemplateDetail = () => {
31
33
  const [data, setData] = useState([]);
32
34
  const [isLoading, setIsLoading] = useState(true);
33
35
 
36
+ // eslint-disable-next-line no-unused-vars
37
+ const [configValues, setConfigValues] = useConfigGlobalState('configValues');
38
+
34
39
  const listIds = useMemo(() => {
35
40
  const configIds = [];
36
41
  // eslint-disable-next-line no-shadow
@@ -45,7 +50,7 @@ const TemplateDetail = () => {
45
50
  configIds.push(item?.configuration?.configuration?.config);
46
51
  }
47
52
  });
48
- return configIds;
53
+ return configIds.filter((id) => id);
49
54
  }, [data]);
50
55
 
51
56
  // eslint-disable-next-line no-shadow
@@ -136,6 +141,32 @@ const TemplateDetail = () => {
136
141
  listIds.length && watchMultiConfigs(listIds);
137
142
  }, [listIds]);
138
143
 
144
+ const getData = useCallback(
145
+ (_item) => {
146
+ if (!_item.configuration) {
147
+ return;
148
+ }
149
+
150
+ const _data = _item?.configuration?.configs.map((config) => {
151
+ const configValue = configValues[config.id]?.value;
152
+ if ([null, undefined, NaN].includes(configValue)) {
153
+ return;
154
+ }
155
+ const value = {
156
+ id: config.id,
157
+ value: configValue,
158
+ evaluate: evaluateValue(
159
+ configValue,
160
+ _item?.configuration?.value_evaluation
161
+ ),
162
+ };
163
+ return { ...config, ...value };
164
+ });
165
+ return _data.filter((value) => value);
166
+ },
167
+ [configValues]
168
+ );
169
+
139
170
  return (
140
171
  <View style={styles.wrap}>
141
172
  <WrapHeaderScrollable
@@ -152,7 +183,7 @@ const TemplateDetail = () => {
152
183
  return (
153
184
  <SensorDisplayItem
154
185
  item={item}
155
- getData={() => {}}
186
+ getData={getData}
156
187
  offsetTitle={'offsetTitle'}
157
188
  setOffsetTitle={'setOffsetTitle'}
158
189
  maxValue={100}
@@ -0,0 +1,18 @@
1
+ import { valueEvaluationFuncs } from '../../Device/hooks/useEvaluateValue';
2
+
3
+ export const evaluateValue = (value, valueEvaluation) => {
4
+ if (!valueEvaluation) {
5
+ return { text: value };
6
+ }
7
+
8
+ const evaluateFunc = valueEvaluationFuncs[valueEvaluation.template];
9
+ if (!evaluateFunc) {
10
+ return { text: value };
11
+ }
12
+
13
+ try {
14
+ return evaluateFunc(value, valueEvaluation.configuration);
15
+ } catch (e) {
16
+ return { text: value };
17
+ }
18
+ };
@@ -44,7 +44,7 @@ const AddMenu = memo(({ unit, afterItemClick, showAdd, setHideAdd }) => {
44
44
  image: <AddDeviceIcon width={43} height={43} />,
45
45
  data: {
46
46
  screen: Routes.SelectDeviceType,
47
- params: { unitId: unit?.id, unitName: unit?.name },
47
+ params: { unit },
48
48
  },
49
49
  },
50
50
  {
@@ -1100,5 +1100,6 @@
1100
1100
  "text_under_development": "This feature is under development.",
1101
1101
  "text_working_hard": "We are working hard to get this running",
1102
1102
  "photo_request_permission": "Photo request permission",
1103
+ "cannot_find_device_wifi": "Cannot find Device's Wifi",
1103
1104
  "photo_request_permission_des": "To select photo from gallery, please unlock access photo permission"
1104
1105
  }
@@ -1099,5 +1099,6 @@
1099
1099
  "text_under_development": "Tính năng này đang được phát triển.",
1100
1100
  "text_working_hard": "Chúng tôi đang làm việc chăm chỉ để làm cho điều này hoạt động",
1101
1101
  "photo_request_permission": "Quyền yêu cầu ảnh",
1102
+ "cannot_find_device_wifi": "Không thể tìm thấy Wifi của thiết bị",
1102
1103
  "photo_request_permission_des": "Để chọn ảnh từ thư viện, vui lòng mở khóa quyền truy cập ảnh"
1103
1104
  }