@eohjsc/react-native-smart-city 0.3.60 → 0.3.61
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/Action/ItemQuickAction.js +9 -3
- package/src/hooks/IoT/__test__/useRemoteControl.test.js +42 -0
- package/src/hooks/IoT/useRemoteControl.js +28 -9
- package/src/iot/RemoteControl/Bluetooth.js +4 -8
- package/src/screens/Device/components/SensorDisplayItem.js +10 -4
- package/src/utils/I18n/translations/en.json +1 -0
- package/src/utils/I18n/translations/vi.json +1 -0
package/package.json
CHANGED
|
@@ -14,6 +14,7 @@ const ItemQuickAction = memo(({ sensor, wrapperStyle, setStatus }) => {
|
|
|
14
14
|
const [isOn, setIsOn] = useState(false);
|
|
15
15
|
|
|
16
16
|
const sendRemoteCommand = useRemoteControl();
|
|
17
|
+
const [processing, setProcessing] = useState(false);
|
|
17
18
|
|
|
18
19
|
useEffect(() => {
|
|
19
20
|
if (!(sensor.quick_action?.config_id in configValues)) {
|
|
@@ -38,7 +39,11 @@ const ItemQuickAction = memo(({ sensor, wrapperStyle, setStatus }) => {
|
|
|
38
39
|
}, [isOn, setStatus, sensor.quick_action]);
|
|
39
40
|
|
|
40
41
|
const userId = useSCContextSelector((state) => state?.auth.account.user.id);
|
|
41
|
-
const onActionPress = useCallback(() => {
|
|
42
|
+
const onActionPress = useCallback(async () => {
|
|
43
|
+
if (processing) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
setProcessing(true);
|
|
42
47
|
let data = null;
|
|
43
48
|
if (
|
|
44
49
|
action?.allow_config_store_value_id === sensor?.quick_action?.config_id
|
|
@@ -56,7 +61,7 @@ const ItemQuickAction = memo(({ sensor, wrapperStyle, setStatus }) => {
|
|
|
56
61
|
}
|
|
57
62
|
data = JSON.stringify(data);
|
|
58
63
|
}
|
|
59
|
-
sendRemoteCommand(sensor, action, data, userId);
|
|
64
|
+
await sendRemoteCommand(sensor, action, data, userId);
|
|
60
65
|
setIsSendingCommand(true);
|
|
61
66
|
|
|
62
67
|
if (!sensor.quick_action.will_auto_update_status) {
|
|
@@ -64,7 +69,8 @@ const ItemQuickAction = memo(({ sensor, wrapperStyle, setStatus }) => {
|
|
|
64
69
|
setIsOn(action.id === sensor.quick_action.on_action.id);
|
|
65
70
|
}, sensor.quick_action.interval);
|
|
66
71
|
}
|
|
67
|
-
|
|
72
|
+
setProcessing(false);
|
|
73
|
+
}, [processing, action, sensor, sendRemoteCommand, userId]);
|
|
68
74
|
|
|
69
75
|
if (!action) {
|
|
70
76
|
return <View />;
|
|
@@ -9,6 +9,7 @@ import { sendCommandOverHomeAssistant } from '../../../iot/RemoteControl/HomeAss
|
|
|
9
9
|
import { sendCommandOverInternet } from '../../../iot/RemoteControl/Internet';
|
|
10
10
|
import { SCProvider } from '../../../context';
|
|
11
11
|
import { mockSCStore } from '../../../context/mockStore';
|
|
12
|
+
import { ToastBottomHelper } from '../../../utils/Utils';
|
|
12
13
|
|
|
13
14
|
jest.mock('../../../iot/RemoteControl/Bluetooth');
|
|
14
15
|
jest.mock('../../../iot/RemoteControl/HomeAssistant');
|
|
@@ -112,6 +113,47 @@ describe('Test useRemoteControl', () => {
|
|
|
112
113
|
expect(sendCommandOverHomeAssistant).not.toBeCalled();
|
|
113
114
|
});
|
|
114
115
|
|
|
116
|
+
const testCommandViaBluetooth = async (
|
|
117
|
+
command_prefer_over_bluetooth,
|
|
118
|
+
command_prefer_over_internet
|
|
119
|
+
) => {
|
|
120
|
+
action.command_prefer_over_bluetooth = command_prefer_over_bluetooth;
|
|
121
|
+
action.command_prefer_over_internet = command_prefer_over_internet;
|
|
122
|
+
action.is_only_bluetooth = true;
|
|
123
|
+
const spyToastError = jest.spyOn(ToastBottomHelper, 'error');
|
|
124
|
+
|
|
125
|
+
const { result: sendRemoteCommand } = renderHook(() => useRemoteControl(), {
|
|
126
|
+
wrapper,
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
sendCommandOverBluetooth.mockImplementation(() => {
|
|
130
|
+
throw SEND_COMMAND_OVER_BLUETOOTH_FAIL;
|
|
131
|
+
});
|
|
132
|
+
sendCommandOverInternet.mockImplementation(async () => true);
|
|
133
|
+
await act(async () => {
|
|
134
|
+
await sendRemoteCommand.current(sensor, action, data, userId);
|
|
135
|
+
});
|
|
136
|
+
expect(sendCommandOverBluetooth).toBeCalledWith(
|
|
137
|
+
sensor,
|
|
138
|
+
action,
|
|
139
|
+
data,
|
|
140
|
+
userId
|
|
141
|
+
);
|
|
142
|
+
expect(sendCommandOverInternet).not.toBeCalled();
|
|
143
|
+
expect(sendCommandOverHomeAssistant).not.toBeCalled();
|
|
144
|
+
expect(spyToastError).toBeCalled();
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
// eslint-disable-next-line max-len
|
|
148
|
+
it('test send remote command via bluetooth failed then not send via internet, action is only bluetooth, not prefer internet', async () => {
|
|
149
|
+
testCommandViaBluetooth(true, false);
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
// eslint-disable-next-line max-len
|
|
153
|
+
it('test send remote command via bluetooth failed then not send via internet, action is only bluetooth, prefer internet', async () => {
|
|
154
|
+
testCommandViaBluetooth(false, true);
|
|
155
|
+
});
|
|
156
|
+
|
|
115
157
|
it('test send remote command via bluetooth failed throw unhandled error', async () => {
|
|
116
158
|
const { result: sendRemoteCommand } = renderHook(() => useRemoteControl(), {
|
|
117
159
|
wrapper,
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
} from '../../iot/RemoteControl/Bluetooth';
|
|
9
9
|
import { ToastBottomHelper } from '../../utils/Utils';
|
|
10
10
|
import { t } from 'i18n-js';
|
|
11
|
+
import NetInfo from '@react-native-community/netinfo';
|
|
11
12
|
|
|
12
13
|
const useRemoteControl = () => {
|
|
13
14
|
const homeAssistantConnections = useSCContextSelector(
|
|
@@ -29,20 +30,38 @@ const useRemoteControl = () => {
|
|
|
29
30
|
try {
|
|
30
31
|
return await sendCommandOverBluetooth(device, action, data, userId);
|
|
31
32
|
} catch (err) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
33
|
+
const netState = await NetInfo.fetch();
|
|
34
|
+
if (netState.isConnected) {
|
|
35
|
+
result = false;
|
|
36
|
+
|
|
37
|
+
if (err === SEND_COMMAND_OVER_BLUETOOTH_FAIL) {
|
|
38
|
+
// Checking only bluetooth: not force internet
|
|
39
|
+
if (!action.is_only_bluetooth) {
|
|
40
|
+
result = await sendCommandOverInternet(
|
|
41
|
+
device,
|
|
42
|
+
action,
|
|
43
|
+
data,
|
|
44
|
+
'bluetooth'
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
return result;
|
|
48
|
+
} else {
|
|
49
|
+
throw err;
|
|
50
|
+
}
|
|
40
51
|
} else {
|
|
41
|
-
|
|
52
|
+
return false;
|
|
42
53
|
}
|
|
43
54
|
}
|
|
44
55
|
}
|
|
45
56
|
|
|
57
|
+
// Checking only bluetooth: not other options
|
|
58
|
+
if (action.is_only_bluetooth) {
|
|
59
|
+
ToastBottomHelper.error(
|
|
60
|
+
t('this_command_is_just_support_bluetooth_only')
|
|
61
|
+
);
|
|
62
|
+
return result;
|
|
63
|
+
}
|
|
64
|
+
|
|
46
65
|
if (action.command_prefer_over_internet) {
|
|
47
66
|
return await sendCommandOverInternet(
|
|
48
67
|
device,
|
|
@@ -140,7 +140,7 @@ export const sendDataOverBluetooth = async (
|
|
|
140
140
|
let connectedDevice = null;
|
|
141
141
|
let fullDataDevice = null;
|
|
142
142
|
let result = true;
|
|
143
|
-
|
|
143
|
+
|
|
144
144
|
try {
|
|
145
145
|
connectedDevice = await device.connect();
|
|
146
146
|
fullDataDevice =
|
|
@@ -148,15 +148,15 @@ export const sendDataOverBluetooth = async (
|
|
|
148
148
|
await fullDataDevice.monitorCharacteristicForService(
|
|
149
149
|
BLE.BLE_REMOTE_SERVICE_UUID,
|
|
150
150
|
BLE.BLE_REMOTE_CHARACTERISTIC_UUID_TX,
|
|
151
|
-
(error, characteristic) => {
|
|
151
|
+
async (error, characteristic) => {
|
|
152
152
|
const notify = error ? '' : base64.decode(characteristic.value);
|
|
153
153
|
if (notify === BLE.BLE_RESPONSE_OK) {
|
|
154
154
|
ToastBottomHelper.success(
|
|
155
155
|
t('control_device_via_bluetooth_successfully')
|
|
156
156
|
);
|
|
157
157
|
if (!keepConnect) {
|
|
158
|
-
bleManager.cancelTransaction(BLE.BLE_LISTER_RESPONSE_CONTROL);
|
|
159
|
-
device.
|
|
158
|
+
await bleManager.cancelTransaction(BLE.BLE_LISTER_RESPONSE_CONTROL);
|
|
159
|
+
await bleManager.cancelDeviceConnection(device.id);
|
|
160
160
|
}
|
|
161
161
|
} else if (notify === BLE.BLE_RESPONSE_FAILED) {
|
|
162
162
|
ToastBottomHelper.error(t('control_device_via_bluetooth_failed'));
|
|
@@ -179,10 +179,6 @@ export const sendDataOverBluetooth = async (
|
|
|
179
179
|
return result;
|
|
180
180
|
}
|
|
181
181
|
|
|
182
|
-
const timeout = setTimeout(() => {
|
|
183
|
-
device.cancelConnection();
|
|
184
|
-
clearTimeout(timeout);
|
|
185
|
-
}, responseTime);
|
|
186
182
|
return result;
|
|
187
183
|
};
|
|
188
184
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useCallback } from 'react';
|
|
1
|
+
import React, { useCallback, useState } from 'react';
|
|
2
2
|
import { View } from 'react-native';
|
|
3
3
|
import ActionGroup from '../../../commons/ActionGroup';
|
|
4
4
|
import { CardDevMode } from '../../../commons/DevMode';
|
|
@@ -46,17 +46,23 @@ export const SensorDisplayItem = ({
|
|
|
46
46
|
const { isEditingTemplate } = useSCContextSelector((state) => state.devMode);
|
|
47
47
|
|
|
48
48
|
const sendRemoteCommand = useRemoteControl();
|
|
49
|
+
const [processing, setProcessing] = useState(false);
|
|
49
50
|
|
|
50
51
|
const doAction = useCallback(
|
|
51
|
-
(action, data) => {
|
|
52
|
-
|
|
52
|
+
async (action, data) => {
|
|
53
|
+
if (processing) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
setProcessing(true);
|
|
57
|
+
await sendRemoteCommand(
|
|
53
58
|
isEditingTemplate ? action?.end_device : sensor,
|
|
54
59
|
action,
|
|
55
60
|
data,
|
|
56
61
|
userId
|
|
57
62
|
);
|
|
63
|
+
setProcessing(false);
|
|
58
64
|
},
|
|
59
|
-
[isEditingTemplate, sensor,
|
|
65
|
+
[processing, sendRemoteCommand, isEditingTemplate, sensor, userId]
|
|
60
66
|
);
|
|
61
67
|
|
|
62
68
|
if (type === 'compass') {
|
|
@@ -1106,5 +1106,6 @@
|
|
|
1106
1106
|
"text_alert_modal_popup_ct": "It’s a critical action and cannot be undone.",
|
|
1107
1107
|
"text_understand_modal_popup_ct": "I fully understand that this action is critical and will lead to data loss.",
|
|
1108
1108
|
"cannot_find_device_wifi": "Cannot find Device's Wifi",
|
|
1109
|
+
"this_command_is_just_support_bluetooth_only": "This command is just support bluetooth only",
|
|
1109
1110
|
"photo_request_permission_des": "To select photo from gallery, please unlock access photo permission"
|
|
1110
1111
|
}
|
|
@@ -1105,5 +1105,6 @@
|
|
|
1105
1105
|
"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",
|
|
1106
1106
|
"photo_request_permission": "Quyền yêu cầu ảnh",
|
|
1107
1107
|
"cannot_find_device_wifi": "Không thể tìm thấy Wifi của thiết bị",
|
|
1108
|
+
"this_command_is_just_support_bluetooth_only": "Lệnh gửi này chỉ hỗ trợ bluetooth",
|
|
1108
1109
|
"photo_request_permission_des": "Để chọn ảnh từ thư viện, vui lòng mở khóa quyền truy cập ảnh"
|
|
1109
1110
|
}
|