@eohjsc/react-native-smart-city 0.3.38 → 0.3.40

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 (51) hide show
  1. package/package.json +1 -1
  2. package/src/commons/AlertAction/index.js +5 -1
  3. package/src/commons/Device/ItemDevice.js +21 -34
  4. package/src/commons/Form/TextInput.js +9 -1
  5. package/src/commons/StatusBox/index.js +19 -0
  6. package/src/commons/StatusBox/styles.js +30 -0
  7. package/src/commons/WrapParallaxScrollView/index.js +6 -1
  8. package/src/commons/index.js +8 -1
  9. package/src/configs/API.js +4 -0
  10. package/src/configs/AccessibilityLabel.js +7 -1
  11. package/src/configs/Colors.js +1 -0
  12. package/src/context/actionType.ts +4 -0
  13. package/src/context/mockStore.ts +3 -0
  14. package/src/context/reducer.ts +17 -0
  15. package/src/hooks/Common/index.js +0 -2
  16. package/src/hooks/Common/useDevicesStatus.js +26 -28
  17. package/src/hooks/IoT/__test__/useRemoteControl.test.js +3 -0
  18. package/src/hooks/IoT/index.js +8 -0
  19. package/src/hooks/IoT/useBluetoothConnection.js +27 -0
  20. package/src/hooks/IoT/useBluetoothDeviceConnected.js +18 -0
  21. package/src/hooks/IoT/useEoHBackendDeviceConnected.js +21 -0
  22. package/src/hooks/{Common → IoT}/useHomeAssistantDeviceConnected.js +0 -0
  23. package/src/hooks/IoT/useRemoteControl.js +8 -19
  24. package/src/iot/RemoteControl/Bluetooth.js +5 -12
  25. package/src/iot/RemoteControl/__test__/Bluetooth.test.js +19 -63
  26. package/src/navigations/UnitStack.js +11 -1
  27. package/src/screens/AddLocationMaps/index.js +1 -0
  28. package/src/screens/AddNewGateway/RenameNewDevices.js +7 -6
  29. package/src/screens/AddNewGateway/ScanGatewayQR.js +2 -6
  30. package/src/screens/AddNewGateway/__test__/ScanGatewayQR.test.js +1 -1
  31. package/src/screens/ConfirmUnitDeletion/index.js +6 -1
  32. package/src/screens/Device/__test__/detail.test.js +1 -0
  33. package/src/screens/Device/detail.js +67 -69
  34. package/src/screens/Gateway/__test__/index.test.js +32 -5
  35. package/src/screens/Gateway/components/GatewayItem/__test__/index.test.js +83 -0
  36. package/src/screens/Gateway/components/GatewayItem/index.js +27 -0
  37. package/src/screens/Gateway/components/GatewayItem/styles.js +62 -0
  38. package/src/screens/Gateway/hooks/useGateway.js +38 -0
  39. package/src/screens/Gateway/index.js +77 -5
  40. package/src/screens/Gateway/styles.js +32 -0
  41. package/src/screens/SubUnit/AddSubUnit.js +5 -1
  42. package/src/screens/Unit/MoreMenu.js +3 -3
  43. package/src/screens/Unit/SelectAddress.js +1 -0
  44. package/src/screens/Unit/components/MyUnitDevice/index.js +1 -1
  45. package/src/screens/Unit/hook/useUnitConnectRemoteDevices.js +11 -8
  46. package/src/screens/UnitSummary/__test__/index.test.js +1 -1
  47. package/src/screens/UnitSummary/components/RunningDevices/__test__/index.test.js +1 -1
  48. package/src/screens/UnitSummary/components/RunningDevices/index.js +3 -17
  49. package/src/utils/I18n/translations/en.json +4 -0
  50. package/src/utils/I18n/translations/vi.json +4 -0
  51. package/src/utils/Route/index.js +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.38",
4
+ "version": "0.3.40",
5
5
  "description": "TODO",
6
6
  "main": "index.js",
7
7
  "files": [
@@ -39,7 +39,11 @@ const AlertAction = ({
39
39
  <Animated.View style={[styles.popoverStyle, animatedStyle]}>
40
40
  <View style={styles.modalWrapper}>
41
41
  <View style={styles.modalHeader}>
42
- <Text semibold style={styles.modalHeaderText}>
42
+ <Text
43
+ semibold
44
+ style={styles.modalHeaderText}
45
+ accessibilityLabel={`${accessibilityLabelPrefix}_TITLE`}
46
+ >
43
47
  {title}
44
48
  </Text>
45
49
  </View>
@@ -11,9 +11,11 @@ import { useNavigation } from '@react-navigation/native';
11
11
  import { useTranslations } from '../../hooks/Common/useTranslations';
12
12
  import ItemQuickAction from '../../commons/Action/ItemQuickAction';
13
13
  import Text from '../../commons/Text';
14
- import { isDeviceConnected as isBluetoothDeviceConnected } from '../../iot/RemoteControl/Bluetooth';
15
- import { useSCContextSelector } from '../../context';
16
- import { useHomeAssistantDeviceConnected } from '../../hooks/Common';
14
+ import {
15
+ useHomeAssistantDeviceConnected,
16
+ useBluetoothDeviceConnected,
17
+ useEoHBackendDeviceConnected,
18
+ } from '../../hooks/IoT';
17
19
 
18
20
  import { Colors } from '../../configs';
19
21
  import {
@@ -27,20 +29,20 @@ const ItemDevice = memo(
27
29
  ({ svgMain, description, title, sensor, unit, station, wrapStyle }) => {
28
30
  const t = useTranslations();
29
31
  const navigation = useNavigation();
30
- const isBluetoothEnabled = useSCContextSelector(
31
- (state) => state.app.isBluetoothEnabled
32
- );
33
- const isNetworkConnected = useSCContextSelector(
34
- (state) => state.app.isNetworkConnected
35
- );
36
- const statuses = useSCContextSelector(
37
- (state) => state.iot.internet.statuses
38
- );
32
+
33
+ const {
34
+ isConnected: isEoHBackendConnected,
35
+ isFetchingStatus: isFetchingStatusFromEoHBackend,
36
+ } = useEoHBackendDeviceConnected(sensor);
37
+
39
38
  const {
40
39
  isConnected: isHomeAssistantConnected,
41
40
  isConnecting: isHomeAssistantConnecting,
42
41
  } = useHomeAssistantDeviceConnected(sensor);
43
42
 
43
+ const { isConnected: isBluetoothConnected } =
44
+ useBluetoothDeviceConnected(sensor);
45
+
44
46
  const goToSensorDisplay = useCallback(() => {
45
47
  navigation.navigate(Routes.DeviceDetail, {
46
48
  unitData: unit,
@@ -50,30 +52,15 @@ const ItemDevice = memo(
50
52
  });
51
53
  }, [navigation, sensor, station, title, unit]);
52
54
 
53
- const isConnectedViaInternet =
54
- isNetworkConnected &&
55
- !!sensor &&
56
- sensor.id in statuses &&
57
- statuses[sensor.id]?.isConnected;
58
-
59
- const isFetchingStatus =
60
- isNetworkConnected && !!sensor && !(sensor.id in statuses);
61
-
62
- const isConnectedViaBLE =
63
- isBluetoothEnabled &&
64
- isBluetoothDeviceConnected(
65
- sensor?.remote_control_options?.bluetooth?.address
66
- );
67
-
68
55
  const borderColor = (() => {
69
56
  if (!!sensor && sensor?.is_managed_by_backend) {
70
57
  if (sensor?.device_type === DEVICE_TYPE.LG_THINQ) {
71
58
  return Colors.Gray4;
72
59
  }
73
- if (isConnectedViaBLE) {
60
+ if (isBluetoothConnected) {
74
61
  return Colors.Gray4;
75
62
  }
76
- if (isFetchingStatus || isConnectedViaInternet) {
63
+ if (isFetchingStatusFromEoHBackend || isEoHBackendConnected) {
77
64
  return Colors.Gray4;
78
65
  }
79
66
  return Colors.Red6;
@@ -92,13 +79,13 @@ const ItemDevice = memo(
92
79
  if (sensor?.device_type === DEVICE_TYPE.LG_THINQ) {
93
80
  return t('connected');
94
81
  }
95
- if (isConnectedViaBLE) {
82
+ if (isBluetoothConnected) {
96
83
  return t('connected');
97
84
  }
98
- if (isFetchingStatus) {
85
+ if (isFetchingStatusFromEoHBackend) {
99
86
  return '';
100
87
  }
101
- if (isConnectedViaInternet) {
88
+ if (isEoHBackendConnected) {
102
89
  return t('connected');
103
90
  }
104
91
  return t('disconnected');
@@ -120,10 +107,10 @@ const ItemDevice = memo(
120
107
  if (sensor?.device_type === DEVICE_TYPE.LG_THINQ) {
121
108
  return true;
122
109
  }
123
- if (isConnectedViaBLE) {
110
+ if (isBluetoothConnected) {
124
111
  return true;
125
112
  }
126
- if (isFetchingStatus) {
113
+ if (isFetchingStatusFromEoHBackend) {
127
114
  return false;
128
115
  }
129
116
  return true;
@@ -29,6 +29,7 @@ const _TextInput = ({
29
29
  accessibilityLabel,
30
30
  selection,
31
31
  onSelectionChange,
32
+ accessibilityLabelError,
32
33
  }) => {
33
34
  const errorStyle = !!errorText && styles.errorWrap;
34
35
  return (
@@ -70,7 +71,14 @@ const _TextInput = ({
70
71
  onSelectionChange={onSelectionChange}
71
72
  />
72
73
  {extraText && extraText}
73
- {!!errorText && <Text style={styles.errorText}>{errorText}</Text>}
74
+ {!!errorText && (
75
+ <Text
76
+ accessibilityLabel={accessibilityLabelError}
77
+ style={styles.errorText}
78
+ >
79
+ {errorText}
80
+ </Text>
81
+ )}
74
82
  </View>
75
83
  );
76
84
  };
@@ -0,0 +1,19 @@
1
+ import React, { memo } from 'react';
2
+ import { View } from 'react-native';
3
+
4
+ import Text from '../Text';
5
+ import styles from './styles';
6
+ import { useTranslations } from '../../hooks/Common/useTranslations';
7
+
8
+ const StatusBox = ({ status }) => {
9
+ const t = useTranslations();
10
+ return (
11
+ <View style={[styles.viewStatus, status && styles.viewOnline]}>
12
+ <Text style={[styles.textStatus, status && styles.textOnline]}>
13
+ {t(status ? 'online' : 'offline')}
14
+ </Text>
15
+ </View>
16
+ );
17
+ };
18
+
19
+ export default memo(StatusBox);
@@ -0,0 +1,30 @@
1
+ import { StyleSheet } from 'react-native';
2
+ import { Colors } from '../../configs';
3
+
4
+ export default StyleSheet.create({
5
+ viewStatus: {
6
+ width: 65,
7
+ paddingHorizontal: 8,
8
+ paddingVertical: 4,
9
+ borderRadius: 54,
10
+ backgroundColor: Colors.White,
11
+ borderColor: Colors.Neutral.Neutral3,
12
+ borderWidth: 1,
13
+ },
14
+ textStatus: {
15
+ fontStyle: 'normal',
16
+ fontWeight: 600,
17
+ letterSpacing: 0.04,
18
+ fontSize: 12,
19
+ lineHeight: 16,
20
+ textTransform: 'uppercase',
21
+ textAlign: 'center',
22
+ },
23
+ textOnline: {
24
+ fontStyle: 'bold',
25
+ },
26
+ viewOnline: {
27
+ backgroundColor: Colors.LightGreen,
28
+ borderWidth: 0,
29
+ },
30
+ });
@@ -37,7 +37,12 @@ const WrapParallaxScrollView = ({
37
37
  hideRightPlus={hideRightPlus}
38
38
  idButtonMore={idButtonMore}
39
39
  />
40
- <Text numberOfLines={1} semibold style={styles.nameUnit}>
40
+ <Text
41
+ numberOfLines={1}
42
+ semibold
43
+ style={styles.nameUnit}
44
+ accessibilityLabel={AccessibilityLabel.HEADER_UNIT_BUTTON_TEXT}
45
+ >
41
46
  {title}
42
47
  </Text>
43
48
  {contentBackground}
@@ -16,7 +16,10 @@ import RadioCircle from './RadioCircle';
16
16
  import { CircleButton } from './CircleButton';
17
17
  import HorizontalPicker from './HorizontalPicker';
18
18
  import FullLoading from './FullLoading';
19
-
19
+ import Text from './Text';
20
+ import { HeaderCustom } from './Header';
21
+ import StatusBox from './StatusBox';
22
+ import WrapHeaderScrollable from './Sharing/WrapHeaderScrollable';
20
23
  export {
21
24
  ButtonPopup,
22
25
  CircleView,
@@ -36,4 +39,8 @@ export {
36
39
  CircleButton,
37
40
  HorizontalPicker,
38
41
  FullLoading,
42
+ Text,
43
+ HeaderCustom,
44
+ StatusBox,
45
+ WrapHeaderScrollable,
39
46
  };
@@ -211,6 +211,10 @@ const API = {
211
211
  GET_TEMPLATES: '/property_manager/iot_dashboard/dev_mode/templates/',
212
212
  GET_WIDGETS: (templateId) =>
213
213
  `/property_manager/iot_dashboard/dev_mode/templates/${templateId}/list_widgets/`,
214
+ GATEWAY: {
215
+ LIST: () => '/chip_manager/developer_mode_chips/',
216
+ DETAIL: (id) => `/chip_manager/developer_mode_chips/${id}/`,
217
+ },
214
218
  },
215
219
  };
216
220
 
@@ -43,6 +43,8 @@ export default {
43
43
 
44
44
  // ConfirmUnitDeletion
45
45
  CONFIRM_UNIT_DELETION_BUTTON: 'CONFIRM_UNIT_DELETION_BUTTON',
46
+ CONFIRM_UNIT_DELETION_CONFIRM_FIELD: 'CONFIRM_UNIT_DELETION_CONFIRM_FIELD',
47
+ CONFIRM_UNIT_DELETION_CONFIRM_ERROR: 'CONFIRM_UNIT_DELETION_CONFIRM_ERROR',
46
48
 
47
49
  //member list
48
50
  SHARING_MEMBER: 'SHARING_MEMBER',
@@ -252,6 +254,8 @@ export default {
252
254
  EMERGENCY_BUTTON: 'EMERGENCY_BUTTON',
253
255
 
254
256
  // ADD SUB UNIT
257
+ ADD_SUB_UNIT_SCREEN: 'ADD_SUB_UNIT_SCREEN',
258
+ ADD_SUB_UNIT_NAME_FIELD: 'ADD_SUB_UNIT_NAME_FIELD',
255
259
  ADD_SUB_UNIT_BUTTON_CHOOSE_PHOTO: 'ADD_SUB_UNIT_BUTTON_CHOOSE_PHOTO',
256
260
  ADD_SUB_UNIT_BUTTON_CHOOSE_LOCATION: 'ADD_SUB_UNIT_BUTTON_CHOOSE_LOCATION',
257
261
 
@@ -440,6 +444,7 @@ export default {
440
444
 
441
445
  // Header Unit
442
446
  HEADER_UNIT_BUTTON_BACK: 'HEADER_UNIT_BUTTON_BACK',
447
+ HEADER_UNIT_BUTTON_TEXT: 'HEADER_UNIT_BUTTON_TEXT',
443
448
  HEADER_UNIT_BUTTON_ADD: 'HEADER_UNIT_BUTTON_ADD',
444
449
  HEADER_UNIT_BUTTON_MORE: 'HEADER_UNIT_BUTTON_MORE',
445
450
 
@@ -633,7 +638,8 @@ export default {
633
638
  BUTTON_CANCEL_EDIT_ACTION_LIST: 'BUTTON_CANCEL_EDIT_ACTION_LIST',
634
639
  BUTTON_SAVE_EDIT_ACTION_LIST: 'BUTTON_SAVE_EDIT_ACTION_LIST',
635
640
  BUTTON_REMOVE_EDIT_ACTION_LIST: 'BUTTON_REMOVE_EDIT_ACTION_LIST',
636
-
641
+ // GATEWAY
642
+ LIST_GATEWAY: 'LIST_GATEWAY',
637
643
  //Notification
638
644
  CUSTOM_TEXT: 'CUSTOM_TEXT',
639
645
  //ButtonWrapper
@@ -60,6 +60,7 @@ export const Colors = {
60
60
  Gray17: '#D3D3D3',
61
61
  Gray18: '#9B9A9B',
62
62
  Gray19: '#E5E5E5',
63
+ Gray20: '#808080',
63
64
 
64
65
  // Range Green
65
66
  Green1: '#F6FFED',
@@ -17,6 +17,7 @@ export const Action = {
17
17
  SET_STARRED_SCRIPTS: 'SET_STARRED_SCRIPTS',
18
18
  STAR_SCRIPTS: 'STAR_SCRIPTS',
19
19
  UNSTAR_SCRIPTS: 'UNSTAR_SCRIPTS',
20
+ SET_BLUETOOTH_CONNECTED_DEVICE: 'SET_BLUETOOTH_CONNECTED_DEVICE',
20
21
  SET_HOME_ASSISTANT_CONNECTIONS: 'SET_HOME_ASSISTANT_CONNECTIONS',
21
22
  CHANGE_HOME_ASSISTANT_CONN_STATE: 'CHANGE_HOME_ASSISTANT_CONN_STATE',
22
23
  SET_LG_THINQ_CONNECTED: 'SET_LG_THINQ_CONNECTED',
@@ -95,6 +96,9 @@ export type AppType = {
95
96
  };
96
97
 
97
98
  export type IoTType = {
99
+ bluetooth: {
100
+ connectedDevices: {};
101
+ };
98
102
  homeassistant: {
99
103
  connections: {};
100
104
  };
@@ -41,6 +41,9 @@ export const mockDataStore: ContextData = {
41
41
  isLockWhenPickColor: false,
42
42
  },
43
43
  iot: {
44
+ bluetooth: {
45
+ connectedDevices: {},
46
+ },
44
47
  homeassistant: {
45
48
  connections: {},
46
49
  },
@@ -68,6 +68,9 @@ export const initialState = {
68
68
  isLockWhenPickColor: false,
69
69
  },
70
70
  iot: {
71
+ bluetooth: {
72
+ connectedDevices: {},
73
+ },
71
74
  homeassistant: {
72
75
  connections: {},
73
76
  },
@@ -291,6 +294,20 @@ export const reducer = (currentState: ContextData, action: Action) => {
291
294
  },
292
295
  };
293
296
 
297
+ case Action.SET_BLUETOOTH_CONNECTED_DEVICE:
298
+ return {
299
+ ...currentState,
300
+ iot: {
301
+ ...currentState.iot,
302
+ bluetooth: {
303
+ ...currentState.iot.bluetooth,
304
+ connectedDevices: {
305
+ ...currentState.iot.bluetooth.connectedDevices,
306
+ [payload.name]: payload.device,
307
+ },
308
+ },
309
+ },
310
+ };
294
311
  case Action.SET_HOME_ASSISTANT_CONNECTIONS:
295
312
  return {
296
313
  ...currentState,
@@ -5,7 +5,6 @@ import useKeyboardShow from './useKeyboardShow';
5
5
  import usePopover from './usePopover';
6
6
  import useTitleHeader from './useTitleHeader';
7
7
  import useDevicesStatus from './useDevicesStatus';
8
- import useHomeAssistantDeviceConnected from './useHomeAssistantDeviceConnected';
9
8
  import { useBlockBackAndroid } from './useBlockBackAndroid';
10
9
  import { useIsOwnerOfUnit } from './useIsOwnerOfUnit';
11
10
  import { useStatusBar } from './useStatusBar';
@@ -23,5 +22,4 @@ export {
23
22
  useStatusBar,
24
23
  useGetIdUser,
25
24
  useDevicesStatus,
26
- useHomeAssistantDeviceConnected,
27
25
  };
@@ -1,6 +1,5 @@
1
- import { useCallback, useContext } from 'react';
2
- import { InteractionManager } from 'react-native';
3
- import { useFocusEffect } from '@react-navigation/native';
1
+ import { useCallback, useContext, useEffect } from 'react';
2
+ import { useIsFocused } from '@react-navigation/native';
4
3
  import { SCContext, useSCContextSelector } from '../../context';
5
4
  import { axiosGet } from '../../utils/Apis/axios';
6
5
  import { API } from '../../configs';
@@ -13,8 +12,13 @@ const useDevicesStatus = (unit, devices) => {
13
12
  const isNetworkConnected = useSCContextSelector(
14
13
  (state) => state.app.isNetworkConnected
15
14
  );
15
+ const isFocused = useIsFocused();
16
16
 
17
17
  const getDevicesStatus = useCallback(async (_unit, _devices) => {
18
+ if (timeoutId) {
19
+ clearTimeout(timeoutId);
20
+ timeoutId = 0;
21
+ }
18
22
  const params = new URLSearchParams();
19
23
  _devices.forEach((device) => {
20
24
  params.append('sensors', device.id);
@@ -30,32 +34,26 @@ const useDevicesStatus = (unit, devices) => {
30
34
  // eslint-disable-next-line react-hooks/exhaustive-deps
31
35
  }, []);
32
36
 
33
- useFocusEffect(
34
- useCallback(() => {
35
- const task = InteractionManager.runAfterInteractions(() => {
36
- if (!devices?.length || !isNetworkConnected) {
37
- return;
38
- }
37
+ useEffect(() => {
38
+ if (!isFocused) {
39
+ return;
40
+ }
41
+ if (!devices?.length || !isNetworkConnected) {
42
+ return;
43
+ }
39
44
 
40
- const managedDevices = devices.filter(
41
- (device) => device?.is_managed_by_backend
42
- );
43
- if (!managedDevices.length) {
44
- return;
45
- }
46
- timeoutId = setTimeout(
47
- () => getDevicesStatus(unit, managedDevices),
48
- 200
49
- );
50
- });
51
-
52
- return () => {
53
- clearTimeout(timeoutId);
54
- task.cancel();
55
- };
56
- // eslint-disable-next-line react-hooks/exhaustive-deps
57
- }, [unit, devices, isNetworkConnected])
58
- );
45
+ const managedDevices = devices.filter(
46
+ (device) => device?.is_managed_by_backend
47
+ );
48
+ if (!managedDevices.length) {
49
+ return;
50
+ }
51
+ getDevicesStatus(unit, devices);
52
+ return () => {
53
+ clearTimeout(timeoutId);
54
+ timeoutId = 0;
55
+ };
56
+ }, [getDevicesStatus, unit, devices, isNetworkConnected, isFocused]);
59
57
  };
60
58
 
61
59
  export default useDevicesStatus;
@@ -88,6 +88,8 @@ describe('Test useRemoteControl', () => {
88
88
  });
89
89
 
90
90
  it('test send remote command via bluetooth failed then send via internet', async () => {
91
+ action.command_prefer_over_bluetooth = true;
92
+ action.command_prefer_over_internet = true;
91
93
  const { result: sendRemoteCommand } = renderHook(() => useRemoteControl(), {
92
94
  wrapper,
93
95
  });
@@ -156,6 +158,7 @@ describe('Test useRemoteControl', () => {
156
158
  data,
157
159
  'internet'
158
160
  );
161
+ expect(sendCommandOverInternet).toBeCalledTimes(1);
159
162
  expect(sendCommandOverBluetooth).not.toBeCalled();
160
163
  expect(sendCommandOverHomeAssistant).not.toBeCalled();
161
164
  expect(sendCommandOverLGThinq).not.toBeCalled();
@@ -1,13 +1,21 @@
1
+ import useBluetoothConnection from './useBluetoothConnection';
1
2
  import useHomeAssistantConnection from './useHomeAssistantConnection';
2
3
  import useRemoteControl from './useRemoteControl';
3
4
  import useValueEvaluations from './useValueEvaluation';
4
5
  import useWatchConfigs from './useWatchConfigs';
5
6
  import useUnwatchLGDeviceConfigControl from './useUnwatchLGDeviceConfigControl';
7
+ import useHomeAssistantDeviceConnected from './useHomeAssistantDeviceConnected';
8
+ import useBluetoothDeviceConnected from './useBluetoothDeviceConnected';
9
+ import useEoHBackendDeviceConnected from './useEoHBackendDeviceConnected';
6
10
 
7
11
  export {
12
+ useBluetoothConnection,
8
13
  useHomeAssistantConnection,
9
14
  useRemoteControl,
10
15
  useValueEvaluations,
11
16
  useWatchConfigs,
12
17
  useUnwatchLGDeviceConfigControl,
18
+ useHomeAssistantDeviceConnected,
19
+ useBluetoothDeviceConnected,
20
+ useEoHBackendDeviceConnected,
13
21
  };
@@ -0,0 +1,27 @@
1
+ import { useContext, useCallback } from 'react';
2
+ import { SCContext } from '../../context';
3
+ import { Action } from '../../context/actionType';
4
+ import { scanBluetoothDevices } from '../../iot/RemoteControl/Bluetooth';
5
+
6
+ const useBluetoothConnection = () => {
7
+ const { setAction } = useContext(SCContext);
8
+
9
+ const onDeviceFound = useCallback(async (name, device) => {
10
+ setAction(Action.SET_BLUETOOTH_CONNECTED_DEVICE, { name, device });
11
+ // eslint-disable-next-line react-hooks/exhaustive-deps
12
+ }, []);
13
+
14
+ const bluetoothScanDevices = useCallback(
15
+ (addresses) => {
16
+ scanBluetoothDevices(addresses, onDeviceFound);
17
+ },
18
+ [onDeviceFound]
19
+ );
20
+
21
+ return {
22
+ onDeviceFound,
23
+ bluetoothScanDevices,
24
+ };
25
+ };
26
+
27
+ export default useBluetoothConnection;
@@ -0,0 +1,18 @@
1
+ import { useSCContextSelector } from '../../context';
2
+
3
+ const useBluetoothDeviceConnected = (device) => {
4
+ const connectedDevices = useSCContextSelector(
5
+ (state) => state.iot.bluetooth.connectedDevices
6
+ );
7
+ const isBluetoothEnabled = useSCContextSelector((state) => {
8
+ return state.app.isBluetoothEnabled;
9
+ });
10
+
11
+ const isConnected =
12
+ isBluetoothEnabled &&
13
+ !!connectedDevices[device?.remote_control_options?.bluetooth?.address];
14
+
15
+ return { isConnected };
16
+ };
17
+
18
+ export default useBluetoothDeviceConnected;
@@ -0,0 +1,21 @@
1
+ import { useSCContextSelector } from '../../context';
2
+
3
+ const useEoHBackendDeviceConnected = (device) => {
4
+ const isNetworkConnected = useSCContextSelector(
5
+ (state) => state.app.isNetworkConnected
6
+ );
7
+ const statuses = useSCContextSelector((state) => state.iot.internet.statuses);
8
+
9
+ const isConnected =
10
+ isNetworkConnected &&
11
+ !!device &&
12
+ device.id in statuses &&
13
+ statuses[device.id]?.isConnected;
14
+
15
+ const isFetchingStatus =
16
+ isNetworkConnected && !!device && !(device.id in statuses);
17
+
18
+ return { isConnected, isFetchingStatus };
19
+ };
20
+
21
+ export default useEoHBackendDeviceConnected;
@@ -15,7 +15,7 @@ const useRemoteControl = () => {
15
15
  );
16
16
 
17
17
  const sendRemoteCommand = useCallback(
18
- async (sensor, action, data, userId) => {
18
+ async (device, action, data, userId) => {
19
19
  // No action, raise not authorized
20
20
  let result = false;
21
21
  if (!action) {
@@ -27,39 +27,28 @@ const useRemoteControl = () => {
27
27
 
28
28
  if (action.command_prefer_over_bluetooth) {
29
29
  try {
30
- result = await sendCommandOverBluetooth(sensor, action, data, userId);
30
+ result = await sendCommandOverBluetooth(device, action, data, userId);
31
31
  } catch (err) {
32
- result = false;
33
- if (err === SEND_COMMAND_OVER_BLUETOOTH_FAIL) {
34
- result = await sendCommandOverInternet(
35
- sensor,
36
- action,
37
- data,
38
- 'bluetooth'
39
- );
40
- } else {
32
+ if (err !== SEND_COMMAND_OVER_BLUETOOTH_FAIL) {
41
33
  throw err;
42
34
  }
35
+ result = false;
43
36
  }
44
37
  }
45
38
 
46
- if (
47
- (action.command_prefer_over_internet ||
48
- action.command_prefer_over_bluetooth) &&
49
- !result
50
- ) {
39
+ if (action.command_prefer_over_internet && !result) {
51
40
  result = await sendCommandOverInternet(
52
- sensor,
41
+ device,
53
42
  action,
54
43
  data,
55
- 'internet'
44
+ action.command_prefer_over_bluetooth ? 'bluetooth' : 'internet'
56
45
  );
57
46
  }
58
47
 
59
48
  if (action.command_prefer_over_googlehome && !result) {
60
49
  result = await sendCommandOverHomeAssistant(
61
50
  homeAssistantConnections,
62
- sensor,
51
+ device,
63
52
  action,
64
53
  data
65
54
  );
@@ -22,24 +22,17 @@ export const clearFoundDevices = () => {
22
22
  }
23
23
  };
24
24
 
25
- bleManager.onStateChange((state) => {
26
- if (state === 'PoweredOn') {
27
- ToastBottomHelper.success(t('text_ble_is_powered_on'));
28
- realScanBluetoothDevices();
29
- }
30
- }, true);
31
-
32
- export const scanBluetoothDevices = (names) => {
25
+ export const scanBluetoothDevices = (names, onDeviceFound) => {
33
26
  names.map((name) => {
34
27
  if (bluetoothDevices[name]) {
35
28
  return;
36
29
  }
37
30
  needToScanDevices.push(name);
38
31
  });
39
- realScanBluetoothDevices();
32
+ realScanBluetoothDevices(onDeviceFound);
40
33
  };
41
34
 
42
- const realScanBluetoothDevices = () => {
35
+ export const realScanBluetoothDevices = (onDeviceFound) => {
43
36
  if (!needToScanDevices.length) {
44
37
  return;
45
38
  }
@@ -67,9 +60,9 @@ const realScanBluetoothDevices = () => {
67
60
  const index = needToScanDevices.indexOf(name);
68
61
  needToScanDevices.splice(index, 1);
69
62
 
70
- ToastBottomHelper.success(t(`Found bluetooth ${name} for remote control`));
71
-
72
63
  bluetoothDevices[name] = device;
64
+ onDeviceFound && onDeviceFound(name, device);
65
+
73
66
  if (!needToScanDevices.length) {
74
67
  try {
75
68
  bleManager.stopDeviceScan();