@eohjsc/react-native-smart-city 0.3.68 → 0.3.70
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/assets/images/Device/inactive-icon.svg +22 -0
- package/package.json +3 -3
- package/src/commons/ActionGroup/ColorPickerTemplateStyles.js +1 -0
- package/src/commons/ActionGroup/NumberUpDownActionTemplateStyle.js +4 -6
- package/src/commons/ActionGroup/OnOffTemplate/OnOffButtonTemplate.js +3 -1
- package/src/commons/ActionGroup/OnOffTemplate/OnOffButtonTemplateStyle.js +3 -8
- package/src/commons/ActionGroup/OnOffTemplate/OnOffSimpleTemplateStyle.js +1 -2
- package/src/commons/ActionGroup/OnOffTemplate/index.js +4 -2
- package/src/commons/ActionGroup/OnOffTemplate/styles.js +7 -0
- package/src/commons/ActionGroup/OneBigButtonTemplate.js +6 -1
- package/src/commons/ActionGroup/OneBigButtonTemplateStyle.js +1 -1
- package/src/commons/ActionGroup/OptionsDropdownActionTemplate.js +2 -1
- package/src/commons/ActionGroup/OptionsDropdownActionTemplateStyle.js +3 -4
- package/src/commons/ActionGroup/SliderRangeTemplate.js +15 -15
- package/src/commons/ActionGroup/SliderRangeTemplateStyles.js +10 -10
- package/src/commons/ActionGroup/StatesGridActionTemplate.js +20 -13
- package/src/commons/ActionGroup/StatesGridActionTemplateStyle.js +23 -9
- package/src/commons/ActionGroup/ThreeButtonTemplate.js +3 -3
- package/src/commons/ActionGroup/ThreeButtonTemplateStyle.js +9 -1
- package/src/commons/ActionGroup/TimerActionTemplateStyles.js +1 -1
- package/src/commons/ActionGroup/TwoButtonTemplate/TwoButtonTemplateStyles.js +1 -1
- package/src/commons/ActionGroup/__test__/OnOffButtonTemplate.test.js +4 -14
- package/src/commons/ActionGroup/__test__/StatesGridActionTemplate.test.js +1 -1
- package/src/commons/ActionGroup/__test__/index.test.js +1 -1
- package/src/commons/ActionGroup/index.js +3 -31
- package/src/commons/CameraDevice/CameraDeviceStyles.js +1 -2
- package/src/commons/DevMode/CardDevMode.js +9 -33
- package/src/commons/DevMode/Styles/CardStyles.js +3 -0
- package/src/commons/Device/PMSensor/PMSensorIndicatorStyles.js +1 -1
- package/src/commons/Device/RainningSensor/CurrentRainSensor.js +15 -7
- package/src/commons/Device/WindDirection/Compass/index.js +1 -0
- package/src/commons/Device/WindSpeed/Anemometer/index.js +6 -2
- package/src/commons/IconComponent/index.js +17 -3
- package/src/commons/Processing/__test__/Connecting.test.js +38 -2
- package/src/commons/Processing/index.js +2 -6
- package/src/context/reducer.ts +9 -4
- package/src/screens/AddNewGateway/ConnectingDevice.js +14 -3
- package/src/screens/AllGateway/DetailConfigActionInternal/index.js +1 -1
- package/src/screens/AllGateway/DetailConfigActionModbus/index.js +2 -2
- package/src/screens/AllGateway/DetailConfigActionZigbee/index.js +4 -4
- package/src/screens/AllGateway/DeviceGatewayInfo/__test__/index.test.js +2 -0
- package/src/screens/AllGateway/DeviceGatewayInfo/index.js +12 -3
- package/src/screens/AllGateway/DeviceInternalDetail/__test__/index.test.js +4 -4
- package/src/screens/AllGateway/components/GatewayItem/index.js +0 -5
- package/src/screens/AllGateway/components/GatewayItem/styles.js +0 -6
- package/src/screens/AllGateway/hooks/useGateway.js +2 -10
- package/src/screens/Device/__test__/detail.test.js +0 -1
- package/src/screens/Device/__test__/sensorDisplayItem.test.js +143 -0
- package/src/screens/Device/components/DetailHistoryChart.js +1 -0
- package/src/screens/Device/components/SensorDisplayItem.js +51 -47
- package/src/screens/Device/detail.js +83 -116
- package/src/screens/Device/styles.js +6 -2
- package/src/screens/Template/utils/ValueEvaluation.test.js +21 -0
- package/src/screens/Unit/ManageUnit.js +9 -9
- package/src/screens/Unit/SelectAddress.js +1 -1
- package/src/screens/Unit/Summaries.js +1 -0
- package/src/screens/Unit/__test__/SelectAddress.test.js +60 -1
- package/src/screens/Unit/__test__/Summaries.test.js +21 -1
- package/src/screens/Unit/components/Header/index.js +13 -8
- package/src/utils/Apis/axios.js +2 -2
|
@@ -1,42 +1,18 @@
|
|
|
1
1
|
import React, { memo } from 'react';
|
|
2
2
|
import { View } from 'react-native';
|
|
3
3
|
import Text from '../Text';
|
|
4
|
-
import { useSCContextSelector } from '../../context';
|
|
5
|
-
import t from '../../hooks/Common/useTranslations';
|
|
6
4
|
import styles from './Styles/CardStyles';
|
|
7
5
|
|
|
8
|
-
const CardDevMode = ({
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
isWrap,
|
|
15
|
-
}) => {
|
|
16
|
-
const { itemDraggingId, isEditingTemplate, isInEditTemplateScreen } =
|
|
17
|
-
useSCContextSelector((state) => state.devMode);
|
|
18
|
-
|
|
19
|
-
if (isEditingTemplate || isWrap) {
|
|
20
|
-
return (
|
|
21
|
-
<View
|
|
22
|
-
style={[
|
|
23
|
-
styles.card,
|
|
24
|
-
isEditingTemplate && styles.isEditingTemplate,
|
|
25
|
-
style,
|
|
26
|
-
id === itemDraggingId && styles.activeCard,
|
|
27
|
-
]}
|
|
28
|
-
>
|
|
29
|
-
<View style={styles.headerTitle}>
|
|
30
|
-
<Text style={styles.headerLeft}>{title}</Text>
|
|
31
|
-
{!!rightHeaderComponent && rightHeaderComponent}
|
|
32
|
-
</View>
|
|
33
|
-
{children}
|
|
34
|
-
{/* // NOTE: For user can not control sensor at EditTemplateScreen */}
|
|
35
|
-
{isInEditTemplateScreen && <View style={styles.editing} />}
|
|
6
|
+
const CardDevMode = ({ title = '', children, rightHeaderComponent }) => {
|
|
7
|
+
return (
|
|
8
|
+
<View style={styles.card}>
|
|
9
|
+
<View style={styles.headerTitle}>
|
|
10
|
+
{!!title && <Text style={styles.headerLeft}>{title}</Text>}
|
|
11
|
+
{!!rightHeaderComponent && rightHeaderComponent}
|
|
36
12
|
</View>
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
13
|
+
{children}
|
|
14
|
+
</View>
|
|
15
|
+
);
|
|
40
16
|
};
|
|
41
17
|
|
|
42
18
|
export default memo(CardDevMode);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { memo } from 'react';
|
|
1
|
+
import React, { memo, useMemo } from 'react';
|
|
2
2
|
import { View, StyleSheet } from 'react-native';
|
|
3
3
|
import LinearGradient from 'react-native-linear-gradient';
|
|
4
4
|
|
|
@@ -7,6 +7,7 @@ import { CircleView } from '../../../commons';
|
|
|
7
7
|
import Text from '../../../commons/Text';
|
|
8
8
|
import IconRain from '../../../../assets/images/Device/rain.svg';
|
|
9
9
|
import IconSunny from '../../../../assets/images/Device/sunny.svg';
|
|
10
|
+
import IconSunnyBlack from '../../../../assets/images/Device/inactive-icon.svg';
|
|
10
11
|
|
|
11
12
|
const CurrentRainSensor = memo(({ data = [] }) => {
|
|
12
13
|
const item = data.length
|
|
@@ -14,9 +15,17 @@ const CurrentRainSensor = memo(({ data = [] }) => {
|
|
|
14
15
|
: {
|
|
15
16
|
evaluate: {},
|
|
16
17
|
};
|
|
17
|
-
const { text, raining, backgroundColor, borderColor } = item.evaluate
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
const { text, raining, backgroundColor, borderColor } = item.evaluate || {};
|
|
19
|
+
const renderIcon = useMemo(() => {
|
|
20
|
+
let icon = <IconSunny />;
|
|
21
|
+
if (raining) {
|
|
22
|
+
icon = <IconRain />;
|
|
23
|
+
} else {
|
|
24
|
+
const isOn = String(text)?.toLowerCase() === 'on';
|
|
25
|
+
icon = isOn ? <IconSunny /> : <IconSunnyBlack width={32} height={32} />;
|
|
26
|
+
}
|
|
27
|
+
return icon;
|
|
28
|
+
}, [raining, text]);
|
|
20
29
|
|
|
21
30
|
return (
|
|
22
31
|
<View style={styles.standard}>
|
|
@@ -33,8 +42,7 @@ const CurrentRainSensor = memo(({ data = [] }) => {
|
|
|
33
42
|
start={{ x: 1, y: 0 }}
|
|
34
43
|
end={{ x: 1, y: 1 }}
|
|
35
44
|
/>
|
|
36
|
-
{
|
|
37
|
-
{/* TODO: change this to general icon */}
|
|
45
|
+
{renderIcon}
|
|
38
46
|
<Text style={styles.text}>{text}</Text>
|
|
39
47
|
</CircleView>
|
|
40
48
|
</View>
|
|
@@ -46,8 +54,8 @@ export default CurrentRainSensor;
|
|
|
46
54
|
const styles = StyleSheet.create({
|
|
47
55
|
standard: {
|
|
48
56
|
flexDirection: 'row',
|
|
49
|
-
marginTop: 16,
|
|
50
57
|
justifyContent: 'center',
|
|
58
|
+
marginBottom: 16,
|
|
51
59
|
},
|
|
52
60
|
flatlistContent: {
|
|
53
61
|
paddingHorizontal: 16,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { memo, useCallback } from 'react';
|
|
1
|
+
import React, { memo, useCallback, useMemo } from 'react';
|
|
2
2
|
import Svg, { Path, Text, Circle } from 'react-native-svg';
|
|
3
3
|
import { View, StyleSheet } from 'react-native';
|
|
4
4
|
|
|
@@ -13,7 +13,6 @@ const { PI } = Math;
|
|
|
13
13
|
const Anemometer = memo(
|
|
14
14
|
({
|
|
15
15
|
data = [],
|
|
16
|
-
maxValue,
|
|
17
16
|
width = 240,
|
|
18
17
|
size = 170,
|
|
19
18
|
strokeWidth = 16,
|
|
@@ -21,12 +20,17 @@ const Anemometer = memo(
|
|
|
21
20
|
startAngle = -45,
|
|
22
21
|
endAngle = 225,
|
|
23
22
|
txtColor = Colors.Gray8,
|
|
23
|
+
item,
|
|
24
24
|
}) => {
|
|
25
25
|
const center = {
|
|
26
26
|
x: size / 2,
|
|
27
27
|
y: size / 2,
|
|
28
28
|
};
|
|
29
29
|
|
|
30
|
+
const maxValue = useMemo(() => {
|
|
31
|
+
return Number(item?.configuration?.max_value) || 60;
|
|
32
|
+
}, [item?.configuration?.max_value]);
|
|
33
|
+
|
|
30
34
|
const value = data.length ? data[0].value : 0;
|
|
31
35
|
const measure = data.length ? data[0].measure : 'm/s';
|
|
32
36
|
|
|
@@ -13,6 +13,8 @@ const IconComponent = memo(
|
|
|
13
13
|
iconSize = 30,
|
|
14
14
|
style,
|
|
15
15
|
color,
|
|
16
|
+
colorInActive,
|
|
17
|
+
active,
|
|
16
18
|
}) => {
|
|
17
19
|
let extraStyle = {
|
|
18
20
|
width: size,
|
|
@@ -45,6 +47,13 @@ const IconComponent = memo(
|
|
|
45
47
|
return isUrl !== null;
|
|
46
48
|
}, [icon]);
|
|
47
49
|
|
|
50
|
+
const colorIcon = useMemo(() => {
|
|
51
|
+
if (isSendingCommand || !active) {
|
|
52
|
+
return colorInActive || Colors.TextGray;
|
|
53
|
+
}
|
|
54
|
+
return color || Colors.Green7;
|
|
55
|
+
}, [active, color, colorInActive, isSendingCommand]);
|
|
56
|
+
|
|
48
57
|
if (!icon) {
|
|
49
58
|
return null;
|
|
50
59
|
}
|
|
@@ -59,16 +68,21 @@ const IconComponent = memo(
|
|
|
59
68
|
return (
|
|
60
69
|
<IconFill
|
|
61
70
|
name={displayIcon}
|
|
62
|
-
color={
|
|
71
|
+
color={colorIcon}
|
|
63
72
|
size={iconSize}
|
|
64
73
|
style={[extraStyle, style]}
|
|
65
74
|
/>
|
|
66
75
|
);
|
|
67
76
|
} else {
|
|
77
|
+
const textLowercase = displayIcon?.toLowerCase();
|
|
78
|
+
const iconCT =
|
|
79
|
+
textLowercase === 'on' || textLowercase === 'off'
|
|
80
|
+
? 'poweroff'
|
|
81
|
+
: displayIcon;
|
|
68
82
|
return (
|
|
69
83
|
<IconOutline
|
|
70
|
-
name={
|
|
71
|
-
color={
|
|
84
|
+
name={iconCT}
|
|
85
|
+
color={colorIcon}
|
|
72
86
|
size={iconSize}
|
|
73
87
|
style={[extraStyle, style]}
|
|
74
88
|
/>
|
|
@@ -6,10 +6,23 @@ import { Text } from 'react-native';
|
|
|
6
6
|
import { SCProvider } from '../../../context';
|
|
7
7
|
import { mockSCStore } from '../../../context/mockStore';
|
|
8
8
|
import { getPusher } from '../../../utils/Pusher';
|
|
9
|
+
import ViewButtonBottom from '../../ViewButtonBottom';
|
|
9
10
|
|
|
10
|
-
const wrapComponent = ({
|
|
11
|
+
const wrapComponent = ({
|
|
12
|
+
onReady,
|
|
13
|
+
onMessage,
|
|
14
|
+
setHidePopupTurnOnGuide,
|
|
15
|
+
setIsRecallChipScan,
|
|
16
|
+
isChangeAddressSuccess,
|
|
17
|
+
}) => (
|
|
11
18
|
<SCProvider initState={mockSCStore({})}>
|
|
12
|
-
<Processing
|
|
19
|
+
<Processing
|
|
20
|
+
onReady={onReady}
|
|
21
|
+
onMessage={onMessage}
|
|
22
|
+
setHidePopupTurnOnGuide={setHidePopupTurnOnGuide}
|
|
23
|
+
setIsRecallChipScan={setIsRecallChipScan}
|
|
24
|
+
isChangeAddressSuccess={isChangeAddressSuccess}
|
|
25
|
+
/>
|
|
13
26
|
</SCProvider>
|
|
14
27
|
);
|
|
15
28
|
describe('Test Processing', () => {
|
|
@@ -74,4 +87,27 @@ describe('Test Processing', () => {
|
|
|
74
87
|
});
|
|
75
88
|
expect(getPusher().unsubscribe).toBeCalledWith(channelName);
|
|
76
89
|
});
|
|
90
|
+
|
|
91
|
+
it('test click ok', async () => {
|
|
92
|
+
const mockSetHidePopupTurnOnGuide = jest.fn();
|
|
93
|
+
const mockSetIsRecallChipScan = jest.fn();
|
|
94
|
+
await act(async () => {
|
|
95
|
+
tree = await create(
|
|
96
|
+
wrapComponent({
|
|
97
|
+
onReady: setChannelName,
|
|
98
|
+
setHidePopupTurnOnGuide: mockSetHidePopupTurnOnGuide,
|
|
99
|
+
setIsRecallChipScan: mockSetIsRecallChipScan,
|
|
100
|
+
isChangeAddressSuccess: true,
|
|
101
|
+
})
|
|
102
|
+
);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
const viewButtonBottom = tree.root.findByType(ViewButtonBottom);
|
|
106
|
+
await act(async () => {
|
|
107
|
+
tree = viewButtonBottom.props.onRightClick();
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
expect(mockSetHidePopupTurnOnGuide).toHaveBeenCalled();
|
|
111
|
+
expect(mockSetIsRecallChipScan).toHaveBeenCalledWith(true);
|
|
112
|
+
});
|
|
77
113
|
});
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import React, { useCallback, useEffect,
|
|
1
|
+
import React, { useCallback, useEffect, useState } from 'react';
|
|
2
2
|
import { View } from 'react-native';
|
|
3
3
|
import * as Progress from 'react-native-progress';
|
|
4
|
-
import uuid from 'uuid';
|
|
5
4
|
|
|
6
5
|
import Text from '../Text';
|
|
7
6
|
import { HeaderCustom } from '../Header';
|
|
@@ -24,11 +23,9 @@ const Processing = ({
|
|
|
24
23
|
setHidePopupTurnOnGuide,
|
|
25
24
|
setIsRecallChipScan,
|
|
26
25
|
isChangeAddressSuccess,
|
|
26
|
+
channelName,
|
|
27
27
|
}) => {
|
|
28
28
|
const t = useTranslations();
|
|
29
|
-
const channelName = useMemo(() => {
|
|
30
|
-
return 'cache-' + uuid.v4();
|
|
31
|
-
}, []);
|
|
32
29
|
|
|
33
30
|
// eslint-disable-next-line no-unused-vars
|
|
34
31
|
const [state, setState] = useState(initState);
|
|
@@ -81,7 +78,6 @@ const Processing = ({
|
|
|
81
78
|
channel.bind('progress', (message) => {
|
|
82
79
|
processMessage(channel, message);
|
|
83
80
|
});
|
|
84
|
-
|
|
85
81
|
return () => {
|
|
86
82
|
getPusher().unsubscribe(channelName);
|
|
87
83
|
};
|
package/src/context/reducer.ts
CHANGED
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
DevModeType,
|
|
15
15
|
BluetoothType,
|
|
16
16
|
} from './actionType';
|
|
17
|
-
import
|
|
17
|
+
import _ from 'lodash';
|
|
18
18
|
import { STORAGE_KEY, removeMultiple } from '../utils/Storage.js';
|
|
19
19
|
|
|
20
20
|
export type ContextData = {
|
|
@@ -257,7 +257,7 @@ export const reducer = (currentState: ContextData, action: Action) => {
|
|
|
257
257
|
...currentState,
|
|
258
258
|
unit: {
|
|
259
259
|
...currentState.unit,
|
|
260
|
-
favoriteDeviceIds: uniq(
|
|
260
|
+
favoriteDeviceIds: _.uniq(
|
|
261
261
|
currentState.unit.favoriteDeviceIds.concat(payload)
|
|
262
262
|
),
|
|
263
263
|
},
|
|
@@ -286,7 +286,7 @@ export const reducer = (currentState: ContextData, action: Action) => {
|
|
|
286
286
|
...currentState,
|
|
287
287
|
automate: {
|
|
288
288
|
...currentState.automate,
|
|
289
|
-
starredScriptIds: uniq(
|
|
289
|
+
starredScriptIds: _.uniq(
|
|
290
290
|
currentState.automate.starredScriptIds.concat(payload)
|
|
291
291
|
),
|
|
292
292
|
},
|
|
@@ -374,6 +374,8 @@ export const reducer = (currentState: ContextData, action: Action) => {
|
|
|
374
374
|
case Action.SET_DEVICES_STATUS:
|
|
375
375
|
// eslint-disable-next-line no-case-declarations
|
|
376
376
|
let newStatuses = currentState.iot.internet.statuses;
|
|
377
|
+
// eslint-disable-next-line no-case-declarations
|
|
378
|
+
let currentStatus = { ...newStatuses };
|
|
377
379
|
(payload || []).map(
|
|
378
380
|
(i) =>
|
|
379
381
|
(newStatuses[i.id] = {
|
|
@@ -381,6 +383,9 @@ export const reducer = (currentState: ContextData, action: Action) => {
|
|
|
381
383
|
isConnected: i.is_connected,
|
|
382
384
|
})
|
|
383
385
|
);
|
|
386
|
+
if (_.isEqual(newStatuses, currentStatus)) {
|
|
387
|
+
return currentState;
|
|
388
|
+
}
|
|
384
389
|
return {
|
|
385
390
|
...currentState,
|
|
386
391
|
iot: {
|
|
@@ -401,7 +406,7 @@ export const reducer = (currentState: ContextData, action: Action) => {
|
|
|
401
406
|
currentState.fetchedValueEvaluationUnits.indexOf(unitId) !== -1
|
|
402
407
|
? currentState.fetchedValueEvaluationUnits
|
|
403
408
|
: [...currentState.fetchedValueEvaluationUnits, unitId],
|
|
404
|
-
valueEvaluations: reduce(
|
|
409
|
+
valueEvaluations: _.reduce(
|
|
405
410
|
data,
|
|
406
411
|
(dict, item) => {
|
|
407
412
|
dict[item.config] = item;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import React, { useCallback, useEffect, useState } from 'react';
|
|
1
|
+
import React, { useCallback, useEffect, useState, useMemo } from 'react';
|
|
2
2
|
import { useNavigation } from '@react-navigation/native';
|
|
3
3
|
import { Alert } from 'react-native';
|
|
4
|
+
import uuid from 'uuid';
|
|
4
5
|
|
|
5
6
|
import Processing from '../../commons/Processing';
|
|
6
7
|
import Routes from '../../utils/Route';
|
|
@@ -41,6 +42,14 @@ const ConnectingDevice = ({
|
|
|
41
42
|
[navigate, renameParams]
|
|
42
43
|
);
|
|
43
44
|
|
|
45
|
+
const channelName = useMemo(() => {
|
|
46
|
+
return 'cache-' + uuid.v4();
|
|
47
|
+
}, []);
|
|
48
|
+
|
|
49
|
+
const onPressContinue = useCallback(() => {
|
|
50
|
+
onReady && onReady(channelName);
|
|
51
|
+
}, [channelName, onReady]);
|
|
52
|
+
|
|
44
53
|
useEffect(() => {
|
|
45
54
|
timeout = setTimeout(() => {
|
|
46
55
|
Alert.alert(t('continue_to_wait'), t('it_has_been_5_minutes'), [
|
|
@@ -50,13 +59,14 @@ const ConnectingDevice = ({
|
|
|
50
59
|
},
|
|
51
60
|
{
|
|
52
61
|
text: t('continue'),
|
|
62
|
+
onPress: onPressContinue,
|
|
53
63
|
},
|
|
54
64
|
]);
|
|
55
|
-
},
|
|
65
|
+
}, 120 * 1000); // when test, it takes more than 3 min
|
|
56
66
|
return () => {
|
|
57
67
|
clearTimeout(timeout);
|
|
58
68
|
};
|
|
59
|
-
}, [fail, goBack, t]);
|
|
69
|
+
}, [fail, goBack, onPressContinue, t]);
|
|
60
70
|
|
|
61
71
|
const onMessage = useCallback(
|
|
62
72
|
(data) => {
|
|
@@ -99,6 +109,7 @@ const ConnectingDevice = ({
|
|
|
99
109
|
setHidePopupTurnOnGuide={setHidePopupTurnOnGuide}
|
|
100
110
|
setIsRecallChipScan={setIsRecallChipScan}
|
|
101
111
|
isChangeAddressSuccess={isChangeAddressSuccess}
|
|
112
|
+
channelName={channelName}
|
|
102
113
|
/>
|
|
103
114
|
);
|
|
104
115
|
};
|
|
@@ -21,7 +21,7 @@ const DetailConfigActionModbus = () => {
|
|
|
21
21
|
} = params;
|
|
22
22
|
|
|
23
23
|
const sa = useMemo(() => {
|
|
24
|
-
if (itemActionConfig?.sa1 && itemActionConfig?.sa2) {
|
|
24
|
+
if (itemActionConfig?.sa1 >= 0 && itemActionConfig?.sa2 >= 0) {
|
|
25
25
|
return calculateStartAddress(
|
|
26
26
|
itemActionConfig?.sa1,
|
|
27
27
|
itemActionConfig?.sa2
|
|
@@ -31,7 +31,7 @@ const DetailConfigActionModbus = () => {
|
|
|
31
31
|
}, [itemActionConfig?.sa1, itemActionConfig?.sa2]);
|
|
32
32
|
|
|
33
33
|
const len = useMemo(() => {
|
|
34
|
-
if (itemActionConfig?.len1 && itemActionConfig?.len2) {
|
|
34
|
+
if (itemActionConfig?.len1 >= 0 && itemActionConfig?.len2 >= 0) {
|
|
35
35
|
return calculateLength(itemActionConfig?.len1, itemActionConfig?.len2);
|
|
36
36
|
}
|
|
37
37
|
return '--';
|
|
@@ -23,18 +23,18 @@ const DetailConfigActionZigbee = () => {
|
|
|
23
23
|
id: 2,
|
|
24
24
|
title: (isConfig && 'key') || (isAction && 'control_payload') || '',
|
|
25
25
|
data:
|
|
26
|
-
(isConfig && itemActionConfig?.
|
|
27
|
-
(isAction && itemActionConfig?.
|
|
26
|
+
(isConfig && itemActionConfig?.key) ||
|
|
27
|
+
(isAction && itemActionConfig?.control_payload) ||
|
|
28
28
|
'--',
|
|
29
29
|
},
|
|
30
30
|
],
|
|
31
31
|
[
|
|
32
32
|
isAction,
|
|
33
33
|
isConfig,
|
|
34
|
-
itemActionConfig?.action?.control_payload,
|
|
35
34
|
itemActionConfig?.action?.name,
|
|
36
|
-
itemActionConfig?.config?.key,
|
|
37
35
|
itemActionConfig?.config?.name,
|
|
36
|
+
itemActionConfig?.control_payload,
|
|
37
|
+
itemActionConfig?.key,
|
|
38
38
|
]
|
|
39
39
|
);
|
|
40
40
|
|
|
@@ -39,6 +39,7 @@ describe('Test DeviceGatewayInfo', () => {
|
|
|
39
39
|
ieee_address: '1111',
|
|
40
40
|
model_name: '1111',
|
|
41
41
|
sensor: { name: 'sensor', connection_time: 30 },
|
|
42
|
+
used_pins: [{ pin_number: 1 }, { pin_number: 2 }],
|
|
42
43
|
},
|
|
43
44
|
isZigbee: true,
|
|
44
45
|
isModbus: false,
|
|
@@ -59,6 +60,7 @@ describe('Test DeviceGatewayInfo', () => {
|
|
|
59
60
|
delay: 0,
|
|
60
61
|
index: '1',
|
|
61
62
|
sensor: { name: 'sensor', connection_time: 30 },
|
|
63
|
+
used_pins: [{ pin_number: 1 }, { pin_number: 2 }],
|
|
62
64
|
},
|
|
63
65
|
isZigbee: false,
|
|
64
66
|
isModbus: true,
|
|
@@ -2,11 +2,20 @@ import React, { memo, useMemo } from 'react';
|
|
|
2
2
|
import { View } from 'react-native';
|
|
3
3
|
import { useRoute } from '@react-navigation/native';
|
|
4
4
|
|
|
5
|
-
import
|
|
5
|
+
import { useTranslations } from '../../../hooks/Common/useTranslations';
|
|
6
6
|
import styles from './styles';
|
|
7
7
|
import Information from '../components/Information';
|
|
8
8
|
|
|
9
|
+
const formatArrayUsedPin = (used_pins) => {
|
|
10
|
+
let strArray = used_pins[0]?.pin_number;
|
|
11
|
+
for (let i = 1; i < used_pins?.length; i++) {
|
|
12
|
+
strArray += ', ' + used_pins[i]?.pin_number;
|
|
13
|
+
}
|
|
14
|
+
return strArray;
|
|
15
|
+
};
|
|
16
|
+
|
|
9
17
|
const DeviceGatewayInfo = () => {
|
|
18
|
+
const t = useTranslations();
|
|
10
19
|
const { params = {} } = useRoute();
|
|
11
20
|
const {
|
|
12
21
|
device = {},
|
|
@@ -35,10 +44,10 @@ const DeviceGatewayInfo = () => {
|
|
|
35
44
|
{
|
|
36
45
|
id: 2,
|
|
37
46
|
title: 'used_pin',
|
|
38
|
-
data: used_pins?.
|
|
47
|
+
data: used_pins?.length ? formatArrayUsedPin(used_pins) : t('no_data'),
|
|
39
48
|
},
|
|
40
49
|
],
|
|
41
|
-
[name, used_pins]
|
|
50
|
+
[name, t, used_pins]
|
|
42
51
|
);
|
|
43
52
|
|
|
44
53
|
const deviceInformationZigbee = useMemo(
|
|
@@ -69,14 +69,14 @@ describe('Test DeviceInternalDetail', () => {
|
|
|
69
69
|
const listConfigReads = [
|
|
70
70
|
{
|
|
71
71
|
id: 1,
|
|
72
|
-
config: { name: 'config1' },
|
|
72
|
+
config: { name: 'config1', is_write: false, is_read: true },
|
|
73
73
|
value_type: 'boolean',
|
|
74
74
|
pin_number: 0,
|
|
75
75
|
pin_mode: 'input',
|
|
76
76
|
},
|
|
77
77
|
{
|
|
78
78
|
id: 2,
|
|
79
|
-
config: { name: 'config2' },
|
|
79
|
+
config: { name: 'config2', is_write: false, is_read: true },
|
|
80
80
|
value_type: 'integer',
|
|
81
81
|
pin_number: 0,
|
|
82
82
|
pin_mode: 'input',
|
|
@@ -85,14 +85,14 @@ describe('Test DeviceInternalDetail', () => {
|
|
|
85
85
|
const listConfigWrites = [
|
|
86
86
|
{
|
|
87
87
|
id: 1,
|
|
88
|
-
config: { name: 'config1' },
|
|
88
|
+
config: { name: 'config1', is_write: true, is_read: false },
|
|
89
89
|
value_type: 'boolean',
|
|
90
90
|
pin_number: 0,
|
|
91
91
|
pin_mode: 'output',
|
|
92
92
|
},
|
|
93
93
|
{
|
|
94
94
|
id: 2,
|
|
95
|
-
config: { name: 'config2' },
|
|
95
|
+
config: { name: 'config2', is_write: true, is_read: true },
|
|
96
96
|
value_type: 'integer',
|
|
97
97
|
pin_number: 0,
|
|
98
98
|
pin_mode: 'output',
|
|
@@ -13,11 +13,6 @@ const GatewayItem = ({ item, onPress }) => {
|
|
|
13
13
|
{item?.name}
|
|
14
14
|
</Text>
|
|
15
15
|
</View>
|
|
16
|
-
<View style={styles.viewValue}>
|
|
17
|
-
<Text type="Body" color={Colors.Gray20} style={styles.textValue}>
|
|
18
|
-
{`${item?.last_healthy?.signal || '--'} dBm`}
|
|
19
|
-
</Text>
|
|
20
|
-
</View>
|
|
21
16
|
<StatusBox status={item?.is_connected} />
|
|
22
17
|
</TouchableOpacity>
|
|
23
18
|
</View>
|
|
@@ -19,17 +19,11 @@ export default StyleSheet.create({
|
|
|
19
19
|
viewTitle: {
|
|
20
20
|
marginBottom: 6,
|
|
21
21
|
},
|
|
22
|
-
viewValue: {
|
|
23
|
-
marginBottom: 6,
|
|
24
|
-
},
|
|
25
22
|
textTitle: {
|
|
26
23
|
lineHeight: 20,
|
|
27
24
|
height: 40,
|
|
28
25
|
fontWeight: '600',
|
|
29
26
|
},
|
|
30
|
-
textValue: {
|
|
31
|
-
fontWeight: '400',
|
|
32
|
-
},
|
|
33
27
|
borderDisconnect: {
|
|
34
28
|
borderColor: Colors.Red10,
|
|
35
29
|
borderWidth: 1,
|
|
@@ -6,10 +6,6 @@ import { axiosGet, axiosDelete, axiosPost } from '../../../utils/Apis/axios';
|
|
|
6
6
|
import API from '../../../configs/API';
|
|
7
7
|
import t from '../../../hooks/Common/useTranslations';
|
|
8
8
|
|
|
9
|
-
const WRITE_PIN_MODE = ['output', 'open_drain', 'pwm'];
|
|
10
|
-
|
|
11
|
-
const READ_PIN_MODE = ['input', 'input_pull_up', 'input_pull_down', 'analog'];
|
|
12
|
-
|
|
13
9
|
export const useGateway = () => {
|
|
14
10
|
const navigation = useNavigation();
|
|
15
11
|
const [refresh, setRefresh] = useState(false);
|
|
@@ -68,12 +64,8 @@ export const useGateway = () => {
|
|
|
68
64
|
API.DEV_MODE.ARDUINO.CONFIG_PINS(gatewayId, deviceId)
|
|
69
65
|
);
|
|
70
66
|
if (success) {
|
|
71
|
-
const config_read = data?.filter((item) =>
|
|
72
|
-
|
|
73
|
-
);
|
|
74
|
-
const config_write = data?.filter((item) =>
|
|
75
|
-
WRITE_PIN_MODE.includes(item?.pin_mode)
|
|
76
|
-
);
|
|
67
|
+
const config_read = data?.filter((item) => item?.config?.is_read);
|
|
68
|
+
const config_write = data?.filter((item) => item?.config?.is_write);
|
|
77
69
|
setDetailDeviceInternal((prev) => ({
|
|
78
70
|
...prev,
|
|
79
71
|
config_read,
|