@eohjsc/react-native-smart-city 0.3.38 → 0.3.39
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 +1 -1
- package/src/commons/AlertAction/index.js +5 -1
- package/src/commons/Device/ItemDevice.js +21 -34
- package/src/commons/Form/TextInput.js +9 -1
- package/src/commons/WrapParallaxScrollView/index.js +6 -1
- package/src/configs/AccessibilityLabel.js +5 -0
- package/src/context/actionType.ts +4 -0
- package/src/context/mockStore.ts +3 -0
- package/src/context/reducer.ts +17 -0
- package/src/hooks/Common/index.js +0 -2
- package/src/hooks/Common/useDevicesStatus.js +26 -28
- package/src/hooks/IoT/__test__/useRemoteControl.test.js +3 -0
- package/src/hooks/IoT/index.js +8 -0
- package/src/hooks/IoT/useBluetoothConnection.js +27 -0
- package/src/hooks/IoT/useBluetoothDeviceConnected.js +18 -0
- package/src/hooks/IoT/useEoHBackendDeviceConnected.js +21 -0
- package/src/hooks/{Common → IoT}/useHomeAssistantDeviceConnected.js +0 -0
- package/src/hooks/IoT/useRemoteControl.js +8 -19
- package/src/iot/RemoteControl/Bluetooth.js +5 -12
- package/src/iot/RemoteControl/__test__/Bluetooth.test.js +19 -63
- package/src/navigations/UnitStack.js +11 -1
- package/src/screens/AddLocationMaps/index.js +1 -0
- package/src/screens/AddNewGateway/RenameNewDevices.js +7 -6
- package/src/screens/AddNewGateway/ScanGatewayQR.js +2 -6
- package/src/screens/AddNewGateway/__test__/ScanGatewayQR.test.js +1 -1
- package/src/screens/ConfirmUnitDeletion/index.js +6 -1
- package/src/screens/Device/__test__/detail.test.js +1 -0
- package/src/screens/Device/detail.js +53 -59
- package/src/screens/SubUnit/AddSubUnit.js +5 -1
- package/src/screens/Unit/MoreMenu.js +3 -3
- package/src/screens/Unit/SelectAddress.js +1 -0
- package/src/screens/Unit/components/MyUnitDevice/index.js +1 -1
- package/src/screens/Unit/hook/useUnitConnectRemoteDevices.js +11 -8
- package/src/screens/UnitSummary/__test__/index.test.js +1 -1
- package/src/screens/UnitSummary/components/RunningDevices/__test__/index.test.js +1 -1
- package/src/screens/UnitSummary/components/RunningDevices/index.js +3 -17
package/package.json
CHANGED
|
@@ -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
|
|
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 {
|
|
15
|
-
|
|
16
|
-
|
|
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
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
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 (
|
|
60
|
+
if (isBluetoothConnected) {
|
|
74
61
|
return Colors.Gray4;
|
|
75
62
|
}
|
|
76
|
-
if (
|
|
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 (
|
|
82
|
+
if (isBluetoothConnected) {
|
|
96
83
|
return t('connected');
|
|
97
84
|
}
|
|
98
|
-
if (
|
|
85
|
+
if (isFetchingStatusFromEoHBackend) {
|
|
99
86
|
return '';
|
|
100
87
|
}
|
|
101
|
-
if (
|
|
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 (
|
|
110
|
+
if (isBluetoothConnected) {
|
|
124
111
|
return true;
|
|
125
112
|
}
|
|
126
|
-
if (
|
|
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 &&
|
|
74
|
+
{!!errorText && (
|
|
75
|
+
<Text
|
|
76
|
+
accessibilityLabel={accessibilityLabelError}
|
|
77
|
+
style={styles.errorText}
|
|
78
|
+
>
|
|
79
|
+
{errorText}
|
|
80
|
+
</Text>
|
|
81
|
+
)}
|
|
74
82
|
</View>
|
|
75
83
|
);
|
|
76
84
|
};
|
|
@@ -37,7 +37,12 @@ const WrapParallaxScrollView = ({
|
|
|
37
37
|
hideRightPlus={hideRightPlus}
|
|
38
38
|
idButtonMore={idButtonMore}
|
|
39
39
|
/>
|
|
40
|
-
<Text
|
|
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}
|
|
@@ -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
|
|
|
@@ -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
|
};
|
package/src/context/mockStore.ts
CHANGED
package/src/context/reducer.ts
CHANGED
|
@@ -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 {
|
|
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
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
if (!isFocused) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (!devices?.length || !isNetworkConnected) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
39
44
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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();
|
package/src/hooks/IoT/index.js
CHANGED
|
@@ -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;
|
|
File without changes
|
|
@@ -15,7 +15,7 @@ const useRemoteControl = () => {
|
|
|
15
15
|
);
|
|
16
16
|
|
|
17
17
|
const sendRemoteCommand = useCallback(
|
|
18
|
-
async (
|
|
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(
|
|
30
|
+
result = await sendCommandOverBluetooth(device, action, data, userId);
|
|
31
31
|
} catch (err) {
|
|
32
|
-
|
|
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
|
-
|
|
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
|
-
|
|
51
|
+
device,
|
|
63
52
|
action,
|
|
64
53
|
data
|
|
65
54
|
);
|
|
@@ -22,24 +22,17 @@ export const clearFoundDevices = () => {
|
|
|
22
22
|
}
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
-
|
|
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();
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import { BleManager } from 'react-native-ble-plx';
|
|
2
|
-
import Toast from 'react-native-toast-message';
|
|
3
|
-
import { getTranslate } from '../../../utils/I18n';
|
|
4
2
|
import '../Bluetooth';
|
|
5
3
|
import {
|
|
6
4
|
scanBluetoothDevices,
|
|
@@ -12,11 +10,13 @@ import {
|
|
|
12
10
|
|
|
13
11
|
const bleManager = new BleManager();
|
|
14
12
|
|
|
13
|
+
const mockOnDeviceFound = jest.fn();
|
|
14
|
+
|
|
15
15
|
describe('Test IOT Bluetooth', () => {
|
|
16
16
|
beforeEach(() => {
|
|
17
|
+
mockOnDeviceFound.mockClear();
|
|
17
18
|
bleManager.startDeviceScan.mockClear();
|
|
18
19
|
bleManager.stopDeviceScan.mockClear();
|
|
19
|
-
Toast.show.mockClear();
|
|
20
20
|
clearNeedToScanDevices();
|
|
21
21
|
clearFoundDevices();
|
|
22
22
|
});
|
|
@@ -26,53 +26,14 @@ describe('Test IOT Bluetooth', () => {
|
|
|
26
26
|
clearNeedToScanDevices();
|
|
27
27
|
});
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
onStateChangeFn('PoweredOn');
|
|
32
|
-
expect(Toast.show).toBeCalledWith({
|
|
33
|
-
type: 'success',
|
|
34
|
-
position: 'bottom',
|
|
35
|
-
text1: getTranslate('en', 'text_ble_is_powered_on'),
|
|
36
|
-
visibilityTime: 1000,
|
|
37
|
-
});
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
it('When bluetooth is powered on but Toast not ready, user does not get notification', async () => {
|
|
41
|
-
const onStateChangeFn = bleManager.onStateChangeFn;
|
|
42
|
-
Toast._ref = null;
|
|
43
|
-
|
|
44
|
-
onStateChangeFn('PoweredOn');
|
|
45
|
-
expect(Toast.show).toBeCalled();
|
|
46
|
-
|
|
47
|
-
Toast._ref = true;
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it('When bluetooth is powered off, user does not get notification', async () => {
|
|
51
|
-
const onStateChangeFn = bleManager.onStateChangeFn;
|
|
52
|
-
onStateChangeFn('PoweredOff');
|
|
53
|
-
expect(Toast.show).not.toBeCalled();
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
it('Scan bluetooth device will init hardware scan', async () => {
|
|
57
|
-
scanBluetoothDevices(['123456']);
|
|
29
|
+
test('Scan bluetooth device will init hardware scan', async () => {
|
|
30
|
+
scanBluetoothDevices(['123456'], mockOnDeviceFound);
|
|
58
31
|
expect(bleManager.startDeviceScan).toBeCalled();
|
|
59
32
|
});
|
|
60
33
|
|
|
61
|
-
|
|
62
|
-
scanBluetoothDevices(['123456']);
|
|
63
|
-
expect(bleManager.startDeviceScan).toBeCalledTimes(1);
|
|
64
|
-
bleManager.onStateChangeFn('PoweredOn');
|
|
65
|
-
expect(bleManager.startDeviceScan).toBeCalledTimes(2);
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
it('When power on, if not looking for bluetooth then hardware will not scan', async () => {
|
|
69
|
-
bleManager.onStateChangeFn('PoweredOn');
|
|
70
|
-
expect(bleManager.startDeviceScan).not.toBeCalled();
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
it('When look for bluetooth name, hardware will auto stop after period of time', async () => {
|
|
34
|
+
test('When look for bluetooth name, hardware will auto stop after period of time', async () => {
|
|
74
35
|
jest.useFakeTimers();
|
|
75
|
-
scanBluetoothDevices(['123456']);
|
|
36
|
+
scanBluetoothDevices(['123456'], mockOnDeviceFound);
|
|
76
37
|
jest.runAllTimers();
|
|
77
38
|
expect(bleManager.stopDeviceScan).toBeCalled();
|
|
78
39
|
});
|
|
@@ -87,13 +48,8 @@ describe('Test IOT Bluetooth', () => {
|
|
|
87
48
|
}
|
|
88
49
|
);
|
|
89
50
|
|
|
90
|
-
scanBluetoothDevices([device.localName]);
|
|
91
|
-
expect(
|
|
92
|
-
type: 'success',
|
|
93
|
-
position: 'bottom',
|
|
94
|
-
text1: 'Found bluetooth 123456 for remote control',
|
|
95
|
-
visibilityTime: 1000,
|
|
96
|
-
});
|
|
51
|
+
scanBluetoothDevices([device.localName], mockOnDeviceFound);
|
|
52
|
+
expect(mockOnDeviceFound).toBeCalledWith(device.localName, device);
|
|
97
53
|
});
|
|
98
54
|
|
|
99
55
|
it('When search bluetooth has error then program does nothing', async () => {
|
|
@@ -107,8 +63,8 @@ describe('Test IOT Bluetooth', () => {
|
|
|
107
63
|
}
|
|
108
64
|
);
|
|
109
65
|
|
|
110
|
-
scanBluetoothDevices([device.name]);
|
|
111
|
-
expect(
|
|
66
|
+
scanBluetoothDevices([device.name], mockOnDeviceFound);
|
|
67
|
+
expect(mockOnDeviceFound).not.toBeCalled();
|
|
112
68
|
});
|
|
113
69
|
|
|
114
70
|
it('When search bluetooth but found another device then program does nothing', async () => {
|
|
@@ -122,8 +78,8 @@ describe('Test IOT Bluetooth', () => {
|
|
|
122
78
|
}
|
|
123
79
|
);
|
|
124
80
|
|
|
125
|
-
scanBluetoothDevices([device.name + 'x']);
|
|
126
|
-
expect(
|
|
81
|
+
scanBluetoothDevices([device.name + 'x'], mockOnDeviceFound);
|
|
82
|
+
expect(mockOnDeviceFound).not.toBeCalled();
|
|
127
83
|
});
|
|
128
84
|
|
|
129
85
|
it('When not found all bluetooth then hardware will continue scan', async () => {
|
|
@@ -135,7 +91,7 @@ describe('Test IOT Bluetooth', () => {
|
|
|
135
91
|
listener(null, device);
|
|
136
92
|
}
|
|
137
93
|
);
|
|
138
|
-
scanBluetoothDevices([device.name, device.name + 'x']);
|
|
94
|
+
scanBluetoothDevices([device.name, device.name + 'x'], mockOnDeviceFound);
|
|
139
95
|
expect(bleManager.stopDeviceScan).not.toBeCalled();
|
|
140
96
|
});
|
|
141
97
|
|
|
@@ -148,7 +104,7 @@ describe('Test IOT Bluetooth', () => {
|
|
|
148
104
|
listener(null, device);
|
|
149
105
|
}
|
|
150
106
|
);
|
|
151
|
-
scanBluetoothDevices([device.name]);
|
|
107
|
+
scanBluetoothDevices([device.name], mockOnDeviceFound);
|
|
152
108
|
expect(bleManager.stopDeviceScan).toBeCalled();
|
|
153
109
|
});
|
|
154
110
|
|
|
@@ -161,12 +117,12 @@ describe('Test IOT Bluetooth', () => {
|
|
|
161
117
|
listener(null, device);
|
|
162
118
|
}
|
|
163
119
|
);
|
|
164
|
-
scanBluetoothDevices([device.name]);
|
|
120
|
+
scanBluetoothDevices([device.name], mockOnDeviceFound);
|
|
165
121
|
expect(bleManager.startDeviceScan).toBeCalled();
|
|
166
122
|
|
|
167
123
|
bleManager.startDeviceScan.mockClear();
|
|
168
124
|
|
|
169
|
-
scanBluetoothDevices([device.name]);
|
|
125
|
+
scanBluetoothDevices([device.name], mockOnDeviceFound);
|
|
170
126
|
expect(bleManager.startDeviceScan).not.toBeCalled();
|
|
171
127
|
});
|
|
172
128
|
|
|
@@ -203,7 +159,7 @@ describe('Test IOT Bluetooth', () => {
|
|
|
203
159
|
listener(null, device);
|
|
204
160
|
}
|
|
205
161
|
);
|
|
206
|
-
scanBluetoothDevices([device.name]);
|
|
162
|
+
scanBluetoothDevices([device.name], mockOnDeviceFound);
|
|
207
163
|
|
|
208
164
|
await sendCommandBluetoothFail({
|
|
209
165
|
remote_control_options: {
|
|
@@ -230,7 +186,7 @@ describe('Test IOT Bluetooth', () => {
|
|
|
230
186
|
listener(null, device);
|
|
231
187
|
}
|
|
232
188
|
);
|
|
233
|
-
scanBluetoothDevices([device.name]);
|
|
189
|
+
scanBluetoothDevices([device.name], mockOnDeviceFound);
|
|
234
190
|
|
|
235
191
|
await sendCommandOverBluetooth(
|
|
236
192
|
{
|
|
@@ -59,6 +59,9 @@ import { axiosGet } from '../utils/Apis/axios';
|
|
|
59
59
|
import { API } from '../configs';
|
|
60
60
|
import SideMenuDetail from '../screens/SideMenuDetail';
|
|
61
61
|
import { styles } from './UnitStackStyles';
|
|
62
|
+
import { useBluetoothConnection } from '../hooks/IoT';
|
|
63
|
+
import { realScanBluetoothDevices } from '../iot/RemoteControl/Bluetooth';
|
|
64
|
+
import { ToastBottomHelper } from '../utils/Utils';
|
|
62
65
|
|
|
63
66
|
const Stack = createStackNavigator();
|
|
64
67
|
|
|
@@ -78,9 +81,16 @@ export const UnitStack = memo((props) => {
|
|
|
78
81
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
79
82
|
}, []);
|
|
80
83
|
|
|
84
|
+
const { onDeviceFound } = useBluetoothConnection();
|
|
85
|
+
|
|
81
86
|
useEffect(() => {
|
|
82
87
|
const subscription = bleManager.onStateChange((state) => {
|
|
83
|
-
|
|
88
|
+
const connected = state === 'PoweredOn';
|
|
89
|
+
setAction(Action.SET_BLUETOOTH_STATE, connected);
|
|
90
|
+
if (connected) {
|
|
91
|
+
ToastBottomHelper.success(t('text_ble_is_powered_on'));
|
|
92
|
+
realScanBluetoothDevices(onDeviceFound);
|
|
93
|
+
}
|
|
84
94
|
}, true);
|
|
85
95
|
|
|
86
96
|
return () => subscription.remove();
|
|
@@ -106,13 +106,13 @@ const RenameNewDevices = memo(({ route }) => {
|
|
|
106
106
|
onChange={updateItemName('sensor', sensor_index)}
|
|
107
107
|
/>
|
|
108
108
|
</View>
|
|
109
|
-
{sensor
|
|
110
|
-
|
|
111
|
-
<View style={styles.device} key={`${end_device
|
|
109
|
+
{(sensor?.end_devices || []).map(
|
|
110
|
+
(end_device, end_device_index) => (
|
|
111
|
+
<View style={styles.device} key={`${end_device?.id}`}>
|
|
112
112
|
<AddDeviceIcon width={43} height={43} />
|
|
113
113
|
<_TextInput
|
|
114
|
-
accessibilityLabel={`${renameLabel}-end_device-${end_device
|
|
115
|
-
value={end_device
|
|
114
|
+
accessibilityLabel={`${renameLabel}-end_device-${end_device?.id}`}
|
|
115
|
+
value={end_device?.name}
|
|
116
116
|
textInputStyle={styles.textItem}
|
|
117
117
|
onChange={updateItemName(
|
|
118
118
|
'end_device',
|
|
@@ -121,7 +121,8 @@ const RenameNewDevices = memo(({ route }) => {
|
|
|
121
121
|
)}
|
|
122
122
|
/>
|
|
123
123
|
</View>
|
|
124
|
-
)
|
|
124
|
+
)
|
|
125
|
+
)}
|
|
125
126
|
</>
|
|
126
127
|
))}
|
|
127
128
|
</View>
|
|
@@ -22,18 +22,14 @@ const ScanGatewayQR = memo(({ route }) => {
|
|
|
22
22
|
setLoading(false);
|
|
23
23
|
return;
|
|
24
24
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
// todo Bang change QR format
|
|
28
|
-
if (['LITE'].indexOf(devicePrefixName) === -1) {
|
|
25
|
+
if (!data?.prefix || !data?.org_slug) {
|
|
29
26
|
setIsInvalidQrCode(true);
|
|
30
27
|
setLoading(false);
|
|
31
28
|
return;
|
|
32
29
|
}
|
|
33
30
|
navigate(Routes.ConnectingWifiGuide, {
|
|
34
31
|
unitId,
|
|
35
|
-
stationId
|
|
36
|
-
prefix: devicePrefixName,
|
|
32
|
+
stationId,
|
|
37
33
|
qrData: data,
|
|
38
34
|
});
|
|
39
35
|
setLoading(true);
|
|
@@ -65,7 +65,7 @@ describe('test scan gateway device QR', () => {
|
|
|
65
65
|
});
|
|
66
66
|
|
|
67
67
|
it('on scan correct QR code', async () => {
|
|
68
|
-
await scanQRCode({
|
|
68
|
+
await scanQRCode({ org_slug: 'eoh', prefix: 'lite' }, jest.fn());
|
|
69
69
|
expect(mockedNavigate).toHaveBeenCalled();
|
|
70
70
|
expect(mockedNavigate.mock.calls[0][0]).toEqual(Routes.ConnectingWifiGuide);
|
|
71
71
|
});
|
|
@@ -49,11 +49,16 @@ const ConfirmUnitDeletion = ({ route }) => {
|
|
|
49
49
|
{t('enter_yes_to_perform')}
|
|
50
50
|
</Text>
|
|
51
51
|
<_TextInput
|
|
52
|
-
placeholder={t('text_password')}
|
|
53
52
|
onChange={onChangePassword}
|
|
54
53
|
errorText={errorText}
|
|
55
54
|
wrapStyle={styles.noMarginTop}
|
|
56
55
|
textInputStyle={styles.textInput}
|
|
56
|
+
accessibilityLabel={
|
|
57
|
+
AccessibilityLabel.CONFIRM_UNIT_DELETION_CONFIRM_FIELD
|
|
58
|
+
}
|
|
59
|
+
accessibilityLabelError={
|
|
60
|
+
AccessibilityLabel.CONFIRM_UNIT_DELETION_CONFIRM_ERROR
|
|
61
|
+
}
|
|
57
62
|
/>
|
|
58
63
|
<View style={styles.buttonWrap}>
|
|
59
64
|
<Button
|
|
@@ -7,59 +7,57 @@ import React, {
|
|
|
7
7
|
useContext,
|
|
8
8
|
} from 'react';
|
|
9
9
|
import { View, TouchableOpacity, Platform } from 'react-native';
|
|
10
|
-
import {
|
|
11
|
-
import moment from 'moment';
|
|
12
|
-
import { get } from 'lodash';
|
|
10
|
+
import { useNavigation } from '@react-navigation/native';
|
|
13
11
|
import { useSelector } from 'react-redux';
|
|
14
12
|
import { IconFill, IconOutline } from '@ant-design/icons-react-native';
|
|
15
13
|
import { Icon } from '@ant-design/react-native';
|
|
16
|
-
import
|
|
14
|
+
import moment from 'moment';
|
|
15
|
+
import { get } from 'lodash';
|
|
16
|
+
|
|
17
|
+
import { SCContext } from '../../context';
|
|
18
|
+
import { Action } from '../../context/actionType';
|
|
19
|
+
import { useSCContextSelector } from '../../context';
|
|
20
|
+
import { useTranslations } from '../../hooks/Common/useTranslations';
|
|
17
21
|
import { useCountUp } from './hooks/useCountUp';
|
|
18
|
-
import { getData as getLocalData } from '../../utils/Storage';
|
|
19
|
-
import { API, Colors } from '../../configs';
|
|
20
|
-
import { axiosGet } from '../../utils/Apis/axios';
|
|
21
|
-
import {
|
|
22
|
-
isDeviceConnected,
|
|
23
|
-
scanBluetoothDevices,
|
|
24
|
-
} from '../../iot/RemoteControl/Bluetooth';
|
|
25
|
-
import WrapHeaderScrollable from '../../commons/Sharing/WrapHeaderScrollable';
|
|
26
|
-
import { getActionComponent } from '../../commons/ActionGroup';
|
|
27
|
-
import { AlertSendConfirm } from '../../commons/EmergencyButton/AlertSendConfirm';
|
|
28
|
-
import { AlertSent } from '../../commons/EmergencyButton/AlertSent';
|
|
29
22
|
import {
|
|
30
23
|
useAlertResolveEmergency,
|
|
31
24
|
useEmergencyButton,
|
|
32
25
|
} from './hooks/useEmergencyButton';
|
|
33
26
|
import { useFavoriteDevice } from './hooks/useFavoriteDevice';
|
|
34
|
-
import BottomButtonView from '../../commons/BottomButtonView';
|
|
35
|
-
import Text from '../../commons/Text';
|
|
36
|
-
import { AlertAction, ButtonPopup, MenuActionMore } from '../../commons';
|
|
37
|
-
import { DEVICE_TYPE, AccessibilityLabel } from '../../configs/Constants';
|
|
38
|
-
import { SCContext } from '../../context';
|
|
39
|
-
import { Action } from '../../context/actionType';
|
|
40
|
-
|
|
41
27
|
import { usePopover } from '../../hooks/Common';
|
|
42
28
|
import { useConfigGlobalState } from '../../iot/states';
|
|
43
|
-
import {
|
|
44
|
-
import styles from './styles';
|
|
45
|
-
import {
|
|
46
|
-
useIsOwnerOfUnit,
|
|
47
|
-
useBoolean,
|
|
48
|
-
useHomeAssistantDeviceConnected,
|
|
49
|
-
} from '../../hooks/Common';
|
|
29
|
+
import { useIsOwnerOfUnit, useBoolean } from '../../hooks/Common';
|
|
50
30
|
import {
|
|
31
|
+
useBluetoothConnection,
|
|
51
32
|
useHomeAssistantConnection,
|
|
52
33
|
useValueEvaluations,
|
|
34
|
+
useBluetoothDeviceConnected,
|
|
35
|
+
useHomeAssistantDeviceConnected,
|
|
36
|
+
useEoHBackendDeviceConnected,
|
|
53
37
|
} from '../../hooks/IoT';
|
|
54
|
-
import { SensorDisplayItem } from './components/SensorDisplayItem';
|
|
55
|
-
import { useSCContextSelector } from '../../context';
|
|
56
|
-
import { EmergencyCountdown } from './components/EmergencyCountdown';
|
|
57
|
-
import { SensorConnectStatusViewHeader } from './components/SensorConnectStatusViewHeader';
|
|
58
38
|
import { useDisconnectedDevice } from './hooks/useDisconnectedDevice';
|
|
59
39
|
import { useEvaluateValue } from './hooks/useEvaluateValue';
|
|
60
40
|
import { useDeviceWatchConfigControl } from './hooks/useDeviceWatchConfigControl';
|
|
41
|
+
|
|
42
|
+
import WrapHeaderScrollable from '../../commons/Sharing/WrapHeaderScrollable';
|
|
43
|
+
import { getActionComponent } from '../../commons/ActionGroup';
|
|
44
|
+
import { AlertSendConfirm } from '../../commons/EmergencyButton/AlertSendConfirm';
|
|
45
|
+
import { AlertSent } from '../../commons/EmergencyButton/AlertSent';
|
|
46
|
+
import BottomButtonView from '../../commons/BottomButtonView';
|
|
47
|
+
import Text from '../../commons/Text';
|
|
48
|
+
import { AlertAction, ButtonPopup, MenuActionMore } from '../../commons';
|
|
49
|
+
import { SensorDisplayItem } from './components/SensorDisplayItem';
|
|
50
|
+
import { EmergencyCountdown } from './components/EmergencyCountdown';
|
|
51
|
+
import { SensorConnectStatusViewHeader } from './components/SensorConnectStatusViewHeader';
|
|
61
52
|
import { Card } from '../../commons/CardShadow';
|
|
62
53
|
import PreventAccess from '../../commons/PreventAccess';
|
|
54
|
+
|
|
55
|
+
import styles from './styles';
|
|
56
|
+
import Routes from '../../utils/Route';
|
|
57
|
+
import { getData as getLocalData } from '../../utils/Storage';
|
|
58
|
+
import { API, Colors } from '../../configs';
|
|
59
|
+
import { DEVICE_TYPE, AccessibilityLabel } from '../../configs/Constants';
|
|
60
|
+
import { axiosGet } from '../../utils/Apis/axios';
|
|
63
61
|
import { notImplemented } from '../../utils/Utils';
|
|
64
62
|
|
|
65
63
|
const DeviceDetail = ({ route }) => {
|
|
@@ -102,20 +100,17 @@ const DeviceDetail = ({ route }) => {
|
|
|
102
100
|
const isNetworkConnected = useSCContextSelector(
|
|
103
101
|
(state) => state.app.isNetworkConnected
|
|
104
102
|
);
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
103
|
+
|
|
104
|
+
const { isConnected: isEoHBackendConnected } =
|
|
105
|
+
useEoHBackendDeviceConnected(sensor);
|
|
106
|
+
|
|
108
107
|
const {
|
|
109
108
|
isConnected: isHomeAssistantConnected,
|
|
110
109
|
isConnecting: isHomeAssistantConnecting,
|
|
111
110
|
} = useHomeAssistantDeviceConnected(sensor);
|
|
112
111
|
|
|
113
|
-
const
|
|
114
|
-
()
|
|
115
|
-
isBluetoothEnabled &&
|
|
116
|
-
isDeviceConnected(sensor?.remote_control_options?.bluetooth?.address),
|
|
117
|
-
[sensor, isBluetoothEnabled]
|
|
118
|
-
);
|
|
112
|
+
const { isConnected: isBluetoothConnected } =
|
|
113
|
+
useBluetoothDeviceConnected(sensor);
|
|
119
114
|
|
|
120
115
|
const isDeviceHasBle = useMemo(() => {
|
|
121
116
|
const action = display.items.filter((item) => item.type === 'action');
|
|
@@ -183,6 +178,8 @@ const DeviceDetail = ({ route }) => {
|
|
|
183
178
|
|
|
184
179
|
const { connectHomeAssistant } = useHomeAssistantConnection();
|
|
185
180
|
|
|
181
|
+
const { bluetoothScanDevices } = useBluetoothConnection();
|
|
182
|
+
|
|
186
183
|
useEffect(() => {
|
|
187
184
|
if (
|
|
188
185
|
unit.remote_control_options &&
|
|
@@ -196,6 +193,14 @@ const DeviceDetail = ({ route }) => {
|
|
|
196
193
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
197
194
|
}, [unit, isNetworkConnected]);
|
|
198
195
|
|
|
196
|
+
useEffect(() => {
|
|
197
|
+
if (controlOptions?.bluetooth) {
|
|
198
|
+
const bluetooth = controlOptions.bluetooth;
|
|
199
|
+
bluetoothScanDevices([bluetooth.address]);
|
|
200
|
+
}
|
|
201
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
202
|
+
}, [controlOptions, unit]);
|
|
203
|
+
|
|
199
204
|
const fetchSensorDetail = useCallback(async () => {
|
|
200
205
|
const { success, data, resp_status } = await axiosGet(
|
|
201
206
|
API.DEVICE.SENSOR_DETAIL(sensorId || sensor?.id)
|
|
@@ -424,16 +429,9 @@ const DeviceDetail = ({ route }) => {
|
|
|
424
429
|
|
|
425
430
|
const { countUpStr } = useCountUp(lastEvent.reportedAt);
|
|
426
431
|
|
|
427
|
-
useEffect(() => {
|
|
428
|
-
if (controlOptions?.bluetooth) {
|
|
429
|
-
const bluetooth = controlOptions.bluetooth;
|
|
430
|
-
scanBluetoothDevices([bluetooth.address]);
|
|
431
|
-
}
|
|
432
|
-
}, [controlOptions, unit]);
|
|
433
|
-
|
|
434
432
|
useEffect(() => {
|
|
435
433
|
fetchDataDeviceDetail();
|
|
436
|
-
}, [sensor, fetchDataDeviceDetail]);
|
|
434
|
+
}, [sensor, isNetworkConnected, fetchDataDeviceDetail]);
|
|
437
435
|
|
|
438
436
|
const onRefresh = useCallback(() => {
|
|
439
437
|
fetchSensorDetail();
|
|
@@ -542,6 +540,7 @@ const DeviceDetail = ({ route }) => {
|
|
|
542
540
|
});
|
|
543
541
|
};
|
|
544
542
|
if (
|
|
543
|
+
isNetworkConnected &&
|
|
545
544
|
sensor?.is_managed_by_backend &&
|
|
546
545
|
sensor?.device_type !== DEVICE_TYPE.LG_THINQ
|
|
547
546
|
) {
|
|
@@ -553,7 +552,7 @@ const DeviceDetail = ({ route }) => {
|
|
|
553
552
|
setLoading((preState) => ({ ...preState, isConnected: false }));
|
|
554
553
|
}
|
|
555
554
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
556
|
-
}, [sensor, display]);
|
|
555
|
+
}, [sensor, display, isNetworkConnected]);
|
|
557
556
|
|
|
558
557
|
const isShowEmergencyResolve =
|
|
559
558
|
display.items.filter(
|
|
@@ -573,6 +572,7 @@ const DeviceDetail = ({ route }) => {
|
|
|
573
572
|
params: { unitId: unit?.id, group },
|
|
574
573
|
});
|
|
575
574
|
}, [navigation, unit?.group, unit?.id]);
|
|
575
|
+
|
|
576
576
|
const isHaveColorSliderTemplate = useMemo(() => {
|
|
577
577
|
let isFlag = false;
|
|
578
578
|
display?.items.some((item) => {
|
|
@@ -592,14 +592,8 @@ const DeviceDetail = ({ route }) => {
|
|
|
592
592
|
return (
|
|
593
593
|
<SensorConnectStatusViewHeader
|
|
594
594
|
sensor={sensor}
|
|
595
|
-
connectedViaNetwork={
|
|
596
|
-
|
|
597
|
-
}
|
|
598
|
-
connectedViaBle={
|
|
599
|
-
(!isNetworkConnected ||
|
|
600
|
-
(isNetworkConnected && !displayValuesData.isConnected)) &&
|
|
601
|
-
isDeviceConnectedViaBle
|
|
602
|
-
}
|
|
595
|
+
connectedViaNetwork={isEoHBackendConnected}
|
|
596
|
+
connectedViaBle={isBluetoothConnected}
|
|
603
597
|
connectedViaHomeAssistant={isHomeAssistantConnected}
|
|
604
598
|
isHomeAssistantConnecting={isHomeAssistantConnecting}
|
|
605
599
|
lastUpdated={displayValuesData.lastUpdated}
|
|
@@ -164,7 +164,10 @@ const AddSubUnit = ({ route }) => {
|
|
|
164
164
|
}, [navigate]);
|
|
165
165
|
|
|
166
166
|
return (
|
|
167
|
-
<SafeAreaView
|
|
167
|
+
<SafeAreaView
|
|
168
|
+
style={styles.wrap}
|
|
169
|
+
accessibilityLabel={AccessibilityLabel.ADD_SUB_UNIT_SCREEN}
|
|
170
|
+
>
|
|
168
171
|
<TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>
|
|
169
172
|
<View style={styles.commonWrap}>
|
|
170
173
|
<View style={styles.commonWrap}>
|
|
@@ -186,6 +189,7 @@ const AddSubUnit = ({ route }) => {
|
|
|
186
189
|
selectionColor={Colors.Primary}
|
|
187
190
|
value={roomName}
|
|
188
191
|
maxLength={50}
|
|
192
|
+
accessibilityLabel={AccessibilityLabel.ADD_SUB_UNIT_NAME_FIELD}
|
|
189
193
|
/>
|
|
190
194
|
|
|
191
195
|
{isAddUnit && (
|
|
@@ -28,19 +28,19 @@ const MoreMenu = memo(
|
|
|
28
28
|
|
|
29
29
|
const listMenuItem = useMemo(() => {
|
|
30
30
|
const RouteManageUnit = {
|
|
31
|
-
id:
|
|
31
|
+
id: 'mange-unit',
|
|
32
32
|
route: Routes.ManageUnit,
|
|
33
33
|
text: t('manage_unit'),
|
|
34
34
|
data: { unitId: unit.id, unit },
|
|
35
35
|
};
|
|
36
36
|
const RouteUnitMemberList = {
|
|
37
|
-
id:
|
|
37
|
+
id: 'unit-member',
|
|
38
38
|
route: Routes.UnitMemberList,
|
|
39
39
|
text: t('members'),
|
|
40
40
|
data: { unitId: unit.id, unit },
|
|
41
41
|
};
|
|
42
42
|
const ListSmartAccount = {
|
|
43
|
-
id:
|
|
43
|
+
id: 'smart-account',
|
|
44
44
|
route: Routes.ListSmartAccount,
|
|
45
45
|
text: t('smart_account'),
|
|
46
46
|
data: { unitId: unit.id, unit },
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { useState, useCallback } from 'react';
|
|
2
2
|
import { StyleSheet, View, TouchableOpacity } from 'react-native';
|
|
3
3
|
import { useNavigation } from '@react-navigation/native';
|
|
4
|
-
import { useHomeAssistantDeviceConnected } from '../../../../hooks/
|
|
4
|
+
import { useHomeAssistantDeviceConnected } from '../../../../hooks/IoT';
|
|
5
5
|
|
|
6
6
|
import ItemQuickAction from '../../../../commons/Action/ItemQuickAction';
|
|
7
7
|
import Text from '../../../../commons/Text';
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { useEffect, useCallback, useContext } from 'react';
|
|
2
2
|
import { SCContext } from '../../../context';
|
|
3
3
|
import { Action } from '../../../context/actionType';
|
|
4
|
-
import { scanBluetoothDevices } from '../../../iot/RemoteControl/Bluetooth';
|
|
5
4
|
import { lgThinqConnect } from '../../../iot/RemoteControl/LG';
|
|
5
|
+
import { useBluetoothConnection } from '../../../hooks/IoT';
|
|
6
6
|
import { useHomeAssistantConnection } from '../../../hooks/IoT';
|
|
7
7
|
import { useSCContextSelector } from '../../../context';
|
|
8
8
|
|
|
@@ -10,6 +10,9 @@ export const useUnitConnectRemoteDevices = (unit) => {
|
|
|
10
10
|
const isNetworkConnected = useSCContextSelector(
|
|
11
11
|
(state) => state.app.isNetworkConnected
|
|
12
12
|
);
|
|
13
|
+
const isBluetoothEnabled = useSCContextSelector((state) => {
|
|
14
|
+
return state.app.isBluetoothEnabled;
|
|
15
|
+
});
|
|
13
16
|
const lqthinqUnitConnected = useSCContextSelector(
|
|
14
17
|
(state) => state.iot.lgthinq.unitConnected
|
|
15
18
|
);
|
|
@@ -17,6 +20,8 @@ export const useUnitConnectRemoteDevices = (unit) => {
|
|
|
17
20
|
|
|
18
21
|
const { connectHomeAssistant } = useHomeAssistantConnection();
|
|
19
22
|
|
|
23
|
+
const { bluetoothScanDevices } = useBluetoothConnection();
|
|
24
|
+
|
|
20
25
|
let lgThinqConnected = false;
|
|
21
26
|
|
|
22
27
|
const onLgThinqConnected = useCallback(() => {
|
|
@@ -37,16 +42,14 @@ export const useUnitConnectRemoteDevices = (unit) => {
|
|
|
37
42
|
);
|
|
38
43
|
|
|
39
44
|
useEffect(() => {
|
|
40
|
-
if (unit?.remote_control_options?.bluetooth) {
|
|
41
|
-
|
|
45
|
+
if (unit?.remote_control_options?.bluetooth && isBluetoothEnabled) {
|
|
46
|
+
bluetoothScanDevices(unit.remote_control_options.bluetooth);
|
|
42
47
|
}
|
|
43
|
-
|
|
48
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
49
|
+
}, [unit, isBluetoothEnabled]);
|
|
44
50
|
|
|
45
51
|
useEffect(() => {
|
|
46
|
-
if (
|
|
47
|
-
unit?.remote_control_options?.googlehome?.length &&
|
|
48
|
-
isNetworkConnected
|
|
49
|
-
) {
|
|
52
|
+
if (unit?.remote_control_options?.googlehome && isNetworkConnected) {
|
|
50
53
|
(async () => {
|
|
51
54
|
await connectHomeAssistant(unit.remote_control_options.googlehome);
|
|
52
55
|
})();
|
|
@@ -1,27 +1,13 @@
|
|
|
1
|
-
import React, { memo
|
|
1
|
+
import React, { memo } from 'react';
|
|
2
2
|
import { StyleSheet, View } from 'react-native';
|
|
3
3
|
import ItemDevice from '../../../../commons/Device/ItemDevice';
|
|
4
|
-
import { scanBluetoothDevices } from '../../../../iot/RemoteControl/Bluetooth';
|
|
5
|
-
import { useHomeAssistantConnection } from '../../../../hooks/IoT';
|
|
6
4
|
import { useDevicesStatus } from '../../../../hooks/Common';
|
|
5
|
+
import { useUnitConnectRemoteDevices } from '../../../Unit/hook/useUnitConnectRemoteDevices';
|
|
7
6
|
|
|
8
7
|
const RunningDevices = memo(({ unit, summaryDetail }) => {
|
|
9
8
|
const { devices } = summaryDetail;
|
|
10
9
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
useEffect(() => {
|
|
14
|
-
if (unit.remote_control_options) {
|
|
15
|
-
if (unit.remote_control_options.bluetooth) {
|
|
16
|
-
scanBluetoothDevices(unit.remote_control_options.bluetooth);
|
|
17
|
-
}
|
|
18
|
-
if (unit.remote_control_options.googlehome) {
|
|
19
|
-
(async () =>
|
|
20
|
-
await connectHomeAssistant(unit.remote_control_options.googlehome))();
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
24
|
-
}, [unit]);
|
|
10
|
+
useUnitConnectRemoteDevices(unit);
|
|
25
11
|
|
|
26
12
|
useDevicesStatus(unit, devices);
|
|
27
13
|
|