@eohjsc/react-native-smart-city 0.4.53 → 0.4.55
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/README.md +23 -0
- package/package.json +1 -1
- package/src/commons/Action/ItemQuickAction.js +42 -16
- package/src/iot/Monitor.js +1 -1
- package/src/screens/Device/components/SensorDisplayItem.js +13 -3
- package/src/screens/Device/hooks/__test__/useEvaluateValue.test.js +105 -34
- package/src/screens/Device/hooks/useEvaluateValue.js +15 -25
package/README.md
CHANGED
|
@@ -35,12 +35,35 @@ import {
|
|
|
35
35
|
AutomateStack,
|
|
36
36
|
NotificationStack,
|
|
37
37
|
} from '@eohjsc/react-native-smart-city';
|
|
38
|
+
import Config from 'react-native-config';
|
|
38
39
|
import { createStackNavigator } from '@react-navigation/stack';
|
|
39
40
|
|
|
40
41
|
// TODO: What to do with the module?
|
|
41
42
|
const Stack = createStackNavigator();
|
|
42
43
|
|
|
43
44
|
const YourStack = () => {
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
useEffect(() => {
|
|
48
|
+
const config = {
|
|
49
|
+
apiRoot: Config.API_ROOT,
|
|
50
|
+
GOOGLE_MAP_API_KEY: Config.GOOGLE_MAP_API_KEY,
|
|
51
|
+
LG_CLIENT_ID: Config.LG_CLIENT_ID,
|
|
52
|
+
LG_REDIRECT_URI_APP: Config.LG_REDIRECT_URI_APP,
|
|
53
|
+
LG_URL: Config.LG_URL,
|
|
54
|
+
VCONNEX_CLIENT_ID: Config.VCONNEX_CLIENT_ID,
|
|
55
|
+
VCONNEX_REDIRECT_URI_APP: Config.VCONNEX_REDIRECT_URI,
|
|
56
|
+
pusherAppKey: Config.PUSHER_APP_KEY,
|
|
57
|
+
pusherAppCluster: Config.PUSHER_APP_CLUSTER,
|
|
58
|
+
language,
|
|
59
|
+
setCurrentSensorDisplay,
|
|
60
|
+
appName: Config.APP_NAME,
|
|
61
|
+
packageName: Config.APP_PACKAGE_NAME, // Your package name is required
|
|
62
|
+
versionCode: Config.APP_VERSION_CODE, // Your app version is required
|
|
63
|
+
};
|
|
64
|
+
initSCConfig(config);
|
|
65
|
+
}, [language, setCurrentSensorDisplay]);
|
|
66
|
+
|
|
44
67
|
// Declare yourAuthObject and params
|
|
45
68
|
return (
|
|
46
69
|
<Stack.Navigator>
|
package/package.json
CHANGED
|
@@ -8,6 +8,16 @@ import IconComponent from '../IconComponent';
|
|
|
8
8
|
|
|
9
9
|
const ItemQuickAction = memo(
|
|
10
10
|
({ sensor, wrapperStyle, setStatus, iconSize = 30 }) => {
|
|
11
|
+
const { quick_action } = sensor || {};
|
|
12
|
+
const {
|
|
13
|
+
config_id,
|
|
14
|
+
off_action,
|
|
15
|
+
on_status,
|
|
16
|
+
on_action,
|
|
17
|
+
off_status,
|
|
18
|
+
interval,
|
|
19
|
+
will_auto_update_status,
|
|
20
|
+
} = quick_action || {};
|
|
11
21
|
const [action, setAction] = useState(sensor.action);
|
|
12
22
|
// eslint-disable-next-line no-unused-vars
|
|
13
23
|
const [configValues, _] = useConfigGlobalState('configValues');
|
|
@@ -17,26 +27,34 @@ const ItemQuickAction = memo(
|
|
|
17
27
|
const [processing, setProcessing] = useState(false);
|
|
18
28
|
|
|
19
29
|
useEffect(() => {
|
|
20
|
-
if (!(
|
|
30
|
+
if (!(config_id in configValues)) {
|
|
21
31
|
return;
|
|
22
32
|
}
|
|
23
|
-
const configValue = configValues[
|
|
33
|
+
const configValue = configValues[config_id];
|
|
24
34
|
setIsOn(configValue?.value);
|
|
25
|
-
}, [
|
|
35
|
+
}, [configValues, config_id]);
|
|
26
36
|
|
|
27
37
|
useEffect(() => {
|
|
28
|
-
if (!
|
|
38
|
+
if (!quick_action) {
|
|
29
39
|
return;
|
|
30
40
|
}
|
|
31
41
|
|
|
32
42
|
if (isOn) {
|
|
33
|
-
setAction(
|
|
34
|
-
setStatus && setStatus(
|
|
43
|
+
setAction(off_action);
|
|
44
|
+
setStatus && setStatus(on_status);
|
|
35
45
|
} else {
|
|
36
|
-
setAction(
|
|
37
|
-
setStatus && setStatus(
|
|
46
|
+
setAction(on_action);
|
|
47
|
+
setStatus && setStatus(off_status);
|
|
38
48
|
}
|
|
39
|
-
}, [
|
|
49
|
+
}, [
|
|
50
|
+
isOn,
|
|
51
|
+
setStatus,
|
|
52
|
+
quick_action,
|
|
53
|
+
off_action,
|
|
54
|
+
on_status,
|
|
55
|
+
on_action,
|
|
56
|
+
off_status,
|
|
57
|
+
]);
|
|
40
58
|
|
|
41
59
|
const userId = useSCContextSelector((state) => state?.auth.account.user.id);
|
|
42
60
|
const onActionPress = useCallback(async () => {
|
|
@@ -46,9 +64,7 @@ const ItemQuickAction = memo(
|
|
|
46
64
|
}
|
|
47
65
|
setProcessing(true);
|
|
48
66
|
let data = null;
|
|
49
|
-
if (
|
|
50
|
-
action?.allow_config_store_value_id === sensor?.quick_action?.config_id
|
|
51
|
-
) {
|
|
67
|
+
if (action?.allow_config_store_value_id === config_id) {
|
|
52
68
|
if (action?.name?.toLowerCase().includes('off')) {
|
|
53
69
|
data = {
|
|
54
70
|
config_id: action?.allow_config_store_value_id,
|
|
@@ -64,13 +80,23 @@ const ItemQuickAction = memo(
|
|
|
64
80
|
}
|
|
65
81
|
await sendRemoteCommand(sensor, action, data, userId);
|
|
66
82
|
|
|
67
|
-
if (!
|
|
83
|
+
if (!will_auto_update_status) {
|
|
68
84
|
setTimeout(() => {
|
|
69
|
-
setIsOn(action.id ===
|
|
70
|
-
},
|
|
85
|
+
setIsOn(action.id === on_action.id);
|
|
86
|
+
}, interval);
|
|
71
87
|
}
|
|
72
88
|
setProcessing(false);
|
|
73
|
-
}, [
|
|
89
|
+
}, [
|
|
90
|
+
processing,
|
|
91
|
+
action,
|
|
92
|
+
config_id,
|
|
93
|
+
sendRemoteCommand,
|
|
94
|
+
sensor,
|
|
95
|
+
userId,
|
|
96
|
+
will_auto_update_status,
|
|
97
|
+
interval,
|
|
98
|
+
on_action?.id,
|
|
99
|
+
]);
|
|
74
100
|
|
|
75
101
|
if (!action) {
|
|
76
102
|
return <View />;
|
package/src/iot/Monitor.js
CHANGED
|
@@ -37,7 +37,7 @@ const watchingConfigs = {};
|
|
|
37
37
|
|
|
38
38
|
export const updateGlobalValue = (configId, value) => {
|
|
39
39
|
const configValues = getConfigGlobalState('configValues');
|
|
40
|
-
|
|
40
|
+
let newConfigValues = { ...configValues };
|
|
41
41
|
newConfigValues[configId] = value;
|
|
42
42
|
setConfigGlobalState('configValues', newConfigValues);
|
|
43
43
|
};
|
|
@@ -36,7 +36,8 @@ export const SensorDisplayItem = ({
|
|
|
36
36
|
}) => {
|
|
37
37
|
const userId = useSCContextSelector((state) => state.auth.account.user.id);
|
|
38
38
|
const { configuration = {}, id: idTemplate } = item;
|
|
39
|
-
const { type, template, uri, id, name, title } =
|
|
39
|
+
const { type, template, uri, id, name, title, value_evaluation } =
|
|
40
|
+
configuration;
|
|
40
41
|
|
|
41
42
|
const sendRemoteCommand = useRemoteControl();
|
|
42
43
|
const [processing, setProcessing] = useState(false);
|
|
@@ -52,8 +53,10 @@ export const SensorDisplayItem = ({
|
|
|
52
53
|
|
|
53
54
|
const data = (item.configuration.configs || []).map((config) => {
|
|
54
55
|
const configValue = configValues[config.id]?.value;
|
|
56
|
+
|
|
55
57
|
const configEvaluate = evaluate[config.id] || {};
|
|
56
58
|
let value = {};
|
|
59
|
+
|
|
57
60
|
if (configValue === null || configValue === undefined) {
|
|
58
61
|
value = {
|
|
59
62
|
id: config.id,
|
|
@@ -64,14 +67,21 @@ export const SensorDisplayItem = ({
|
|
|
64
67
|
value = {
|
|
65
68
|
id: config.id,
|
|
66
69
|
value: configValue,
|
|
67
|
-
evaluate:
|
|
70
|
+
evaluate:
|
|
71
|
+
evaluateValue(configValue, value_evaluation) || configEvaluate,
|
|
68
72
|
};
|
|
69
73
|
}
|
|
70
74
|
return { ...config, ...value };
|
|
71
75
|
});
|
|
72
76
|
|
|
73
77
|
return data.filter(Boolean);
|
|
74
|
-
}, [
|
|
78
|
+
}, [
|
|
79
|
+
configValues,
|
|
80
|
+
evaluate,
|
|
81
|
+
evaluateValue,
|
|
82
|
+
item.configuration,
|
|
83
|
+
value_evaluation,
|
|
84
|
+
]);
|
|
75
85
|
|
|
76
86
|
const doAction = useCallback(
|
|
77
87
|
async (action, data) => {
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
1
|
import { renderHook } from '@testing-library/react-hooks';
|
|
3
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
useEvaluateValue,
|
|
4
|
+
useGetEvaluateValue,
|
|
5
|
+
valueEvaluationFuncs,
|
|
6
|
+
} from '../useEvaluateValue';
|
|
7
|
+
import React from 'react';
|
|
4
8
|
import { SCProvider } from '../../../../context';
|
|
5
9
|
import { mockSCStore } from '../../../../context/mockStore';
|
|
6
10
|
import { API } from '../../../../configs';
|
|
@@ -24,7 +28,7 @@ const mockUseContext = jest.fn().mockImplementation(() => ({
|
|
|
24
28
|
|
|
25
29
|
React.useContext = mockUseContext;
|
|
26
30
|
|
|
27
|
-
describe('
|
|
31
|
+
describe('useEvaluateValue', () => {
|
|
28
32
|
let valueEvaluations = {};
|
|
29
33
|
|
|
30
34
|
beforeEach(() => {
|
|
@@ -58,50 +62,117 @@ describe('Test useEvaluateValue', () => {
|
|
|
58
62
|
};
|
|
59
63
|
});
|
|
60
64
|
|
|
61
|
-
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
65
|
+
test('should evaluate range correctly', () => {
|
|
66
|
+
const value = 1.2;
|
|
67
|
+
const valueEvaluation = {
|
|
68
|
+
id: 8662,
|
|
69
|
+
template: 'range',
|
|
70
|
+
configuration: {
|
|
71
|
+
ranges: [
|
|
72
|
+
{
|
|
73
|
+
end: 1,
|
|
74
|
+
start: 1,
|
|
75
|
+
evaluate: {
|
|
76
|
+
icon: 'CheckCircleOutlined',
|
|
77
|
+
text: 'Active',
|
|
78
|
+
borderColor: '#00d084',
|
|
79
|
+
backgroundColor: 'rgba(0, 208, 132, 0.3)',
|
|
80
|
+
},
|
|
81
|
+
end_condition: '<',
|
|
82
|
+
start_condition: '>=',
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
end: 0,
|
|
86
|
+
start: 0,
|
|
87
|
+
evaluate: {
|
|
88
|
+
icon: 'CheckCircleOutlined',
|
|
89
|
+
text: 'InActive',
|
|
90
|
+
borderColor: '#abb8c3',
|
|
91
|
+
backgroundColor: 'rgba(171, 184, 195, 0.3)',
|
|
92
|
+
},
|
|
93
|
+
end_condition: '<',
|
|
94
|
+
start_condition: '>=',
|
|
95
|
+
},
|
|
96
|
+
],
|
|
97
|
+
},
|
|
98
|
+
configs: [28265],
|
|
99
|
+
};
|
|
65
100
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
});
|
|
101
|
+
const { result } = renderHook(() => useEvaluateValue());
|
|
102
|
+
const evaluateValue = result.current;
|
|
69
103
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
104
|
+
const evaluatedResult = evaluateValue(value, valueEvaluation);
|
|
105
|
+
expect(evaluatedResult).toEqual({
|
|
106
|
+
backgroundColor: 'rgba(171, 184, 195, 0.3)',
|
|
107
|
+
borderColor: '#abb8c3',
|
|
108
|
+
icon: 'CheckCircleOutlined',
|
|
109
|
+
text: 'InActive',
|
|
73
110
|
});
|
|
74
|
-
|
|
75
|
-
expect(evaluateValue.current(3, 1)).toBe(null);
|
|
76
111
|
});
|
|
77
112
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
113
|
+
test('should evaluate boolean correctly', () => {
|
|
114
|
+
const value = 0;
|
|
115
|
+
const valueEvaluation = {
|
|
116
|
+
id: 8662,
|
|
117
|
+
template: 'boolean',
|
|
118
|
+
configuration: {
|
|
119
|
+
on: {
|
|
120
|
+
value: 1,
|
|
121
|
+
evaluate: {
|
|
122
|
+
text: 'On',
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
off: {
|
|
126
|
+
value: 0,
|
|
127
|
+
evaluate: {
|
|
128
|
+
text: 'Off',
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
configs: [28265],
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
const { result } = renderHook(() => useEvaluateValue());
|
|
136
|
+
const evaluateValue = result.current;
|
|
83
137
|
|
|
84
|
-
|
|
138
|
+
const evaluatedResult = evaluateValue(value, valueEvaluation);
|
|
139
|
+
expect(evaluatedResult).toEqual({ text: 'Off' });
|
|
85
140
|
});
|
|
86
141
|
|
|
87
|
-
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
142
|
+
test('should handle unknown valueEvaluation template', () => {
|
|
143
|
+
const value = 0;
|
|
144
|
+
const configuration = {};
|
|
145
|
+
|
|
146
|
+
const { result } = renderHook(() => useEvaluateValue());
|
|
147
|
+
const evaluateValue = result.current;
|
|
91
148
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
149
|
+
const expectedResult = { text: value };
|
|
150
|
+
const evaluatedResult = evaluateValue(
|
|
151
|
+
value,
|
|
152
|
+
'unknown-template',
|
|
153
|
+
configuration
|
|
154
|
+
);
|
|
155
|
+
expect(evaluatedResult).toEqual(expectedResult);
|
|
95
156
|
});
|
|
96
157
|
|
|
97
|
-
|
|
98
|
-
const
|
|
99
|
-
|
|
158
|
+
test('should handle error in evaluateFunc', () => {
|
|
159
|
+
const value = 0;
|
|
160
|
+
const configuration = {};
|
|
161
|
+
|
|
162
|
+
const { result } = renderHook(() => useEvaluateValue());
|
|
163
|
+
const evaluateValue = result.current;
|
|
164
|
+
|
|
165
|
+
// Mocking a faulty evaluateFunc that throws an error
|
|
166
|
+
valueEvaluationFuncs.range = jest.fn(() => {
|
|
167
|
+
throw new Error('Evaluation error');
|
|
100
168
|
});
|
|
101
169
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
170
|
+
const evaluatedResult = evaluateValue(
|
|
171
|
+
value,
|
|
172
|
+
valueEvaluationFuncs.range,
|
|
173
|
+
configuration
|
|
174
|
+
);
|
|
175
|
+
expect(evaluatedResult).toEqual({ text: 0 });
|
|
105
176
|
});
|
|
106
177
|
|
|
107
178
|
it('test evaluate fetch from server if not exists', async () => {
|
|
@@ -13,6 +13,7 @@ const evaluateRange = (value, configuration) => {
|
|
|
13
13
|
]
|
|
14
14
|
}
|
|
15
15
|
*/
|
|
16
|
+
|
|
16
17
|
if (!value) {
|
|
17
18
|
value = 0;
|
|
18
19
|
}
|
|
@@ -65,34 +66,23 @@ export const valueEvaluationFuncs = {
|
|
|
65
66
|
};
|
|
66
67
|
|
|
67
68
|
export const useEvaluateValue = () => {
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
const evaluateValue = useCallback(
|
|
73
|
-
(configId, value) => {
|
|
74
|
-
if (value === null || value === undefined) {
|
|
75
|
-
return { text: '--', color: null };
|
|
76
|
-
}
|
|
69
|
+
const evaluateValue = useCallback((value, valueEvaluation) => {
|
|
70
|
+
if (valueEvaluation === null || valueEvaluation === undefined) {
|
|
71
|
+
return { text: '--', color: null };
|
|
72
|
+
}
|
|
77
73
|
|
|
78
|
-
|
|
79
|
-
if (!valueEvaluation) {
|
|
80
|
-
return null;
|
|
81
|
-
}
|
|
74
|
+
const evaluateFunc = valueEvaluationFuncs[valueEvaluation.template];
|
|
82
75
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
}
|
|
76
|
+
if (!evaluateFunc) {
|
|
77
|
+
return { text: value };
|
|
78
|
+
}
|
|
87
79
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
[valueEvaluations]
|
|
95
|
-
);
|
|
80
|
+
try {
|
|
81
|
+
return evaluateFunc(value, valueEvaluation.configuration);
|
|
82
|
+
} catch (e) {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
}, []);
|
|
96
86
|
|
|
97
87
|
return evaluateValue;
|
|
98
88
|
};
|