@eohjsc/react-native-smart-city 0.7.40 → 0.7.42
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/Dashboard/MyDashboardDevice/index.js +14 -12
- package/src/commons/Dashboard/MyUnit/index.js +4 -3
- package/src/commons/DateTimeRangeChange/index.js +5 -5
- package/src/commons/Device/HorizontalBarChart.js +11 -24
- package/src/commons/Device/PowerConsumptionChart.js +195 -103
- package/src/commons/FieldTemplate/ChooseUserField/index.js +5 -1
- package/src/commons/Form/CurrencyInput.js +9 -18
- package/src/commons/SelectGateway/index.js +2 -1
- package/src/commons/SelectSubUnit/index.js +5 -1
- package/src/commons/SelectUnit/index.js +1 -1
- package/src/commons/SubUnit/Favorites/index.js +35 -10
- package/src/commons/SubUnit/ShortDetail.js +17 -4
- package/src/commons/SubUnit/__test__/Favorites.test.js +90 -0
- package/src/commons/SubUnit/__test__/ShortDetail.test.js +45 -2
- package/src/commons/UnitSummary/ConfigHistoryChart/index.js +17 -9
- package/src/hooks/IoT/__test__/useValueEvaluation.test.js +12 -12
- package/src/hooks/IoT/useValueEvaluation.js +7 -3
- package/src/hooks/IoT/useWatchSharedChips.js +8 -4
- package/src/hooks/useMqtt.js +8 -4
- package/src/iot/UpdateStates.js +37 -16
- package/src/iot/mqtt.js +23 -0
- package/src/navigations/AutomateStack.js +5 -1
- package/src/screens/ActivityLog/hooks/index.js +12 -4
- package/src/screens/AddLocationMaps/index.js +6 -3
- package/src/screens/AddNewGateway/RenameNewDevices.js +2 -1
- package/src/screens/Automate/AddNewAction/ChooseConfig.js +2 -1
- package/src/screens/Automate/AddNewAction/ReceiverSelect.js +5 -1
- package/src/screens/Automate/MultiUnits.js +2 -1
- package/src/screens/Automate/ScriptDetail/index.js +11 -3
- package/src/screens/Automate/hooks/useAction.js +3 -1
- package/src/screens/Device/__test__/DeviceDetail-3rdparty.test.js +16 -5
- package/src/screens/Device/__test__/DeviceDetail-arduino.test.js +10 -0
- package/src/screens/Device/__test__/DeviceDetail-modbus.test.js +37 -8
- package/src/screens/Device/__test__/DeviceDetail-zigbee.test.js +16 -5
- package/src/screens/Device/__test__/DeviceDetail.test.js +17 -6
- package/src/screens/Device/__test__/sensorDisplayItem.test.js +47 -11
- package/src/screens/Device/components/SensorDisplayItem.js +23 -5
- package/src/screens/Device/detail.js +10 -3
- package/src/screens/Device/hooks/useEvaluateValue.js +7 -3
- package/src/screens/Device/styles.js +4 -0
- package/src/screens/SelectUnit/index.js +3 -1
- package/src/screens/Sharing/InfoMemberUnit.js +3 -1
- package/src/screens/SideMenuDetail/index.js +3 -1
- package/src/screens/Unit/SelectAddToFavorites.js +6 -2
- package/src/screens/UnitSummary/components/3PPowerConsumption/index.js +8 -48
- package/src/screens/UnitSummary/components/PowerConsumption/__test__/PowerConsumption.test.js +121 -6
- package/src/screens/UnitSummary/components/PowerConsumption/index.js +6 -46
- package/src/screens/UnitSummary/index.js +2 -1
- package/src/utils/I18n/translations/en.js +1 -0
- package/src/utils/I18n/translations/vi.js +1 -0
- package/src/utils/chartHelper/index.js +53 -0
- package/src/utils/chartHelper/getMaxValueIndex.js +0 -11
|
@@ -4,6 +4,10 @@ import { useNavigation } from '@react-navigation/native';
|
|
|
4
4
|
import { useTranslations } from '../../../hooks/Common/useTranslations';
|
|
5
5
|
import { useDevicesStatus } from '../../../hooks/Common';
|
|
6
6
|
import { useWatchConfigs } from '../../../hooks/IoT';
|
|
7
|
+
import useChipJsonConfiguration, {
|
|
8
|
+
useConnectChipMqtt,
|
|
9
|
+
} from '../../../hooks/useMqtt';
|
|
10
|
+
import useWatchSharedChips from '../../../hooks/IoT/useWatchSharedChips';
|
|
7
11
|
|
|
8
12
|
import { Section } from '../../Section';
|
|
9
13
|
import ItemDevice from '../../Device/ItemDevice';
|
|
@@ -11,7 +15,6 @@ import ItemOneTap from '../OneTap/ItemOneTap';
|
|
|
11
15
|
import ItemAddNew from '../../Device/ItemAddNew';
|
|
12
16
|
import styles from './styles';
|
|
13
17
|
import Routes from '../../../utils/Route';
|
|
14
|
-
import { DEVICE_TYPE } from '../../../configs/Constants';
|
|
15
18
|
|
|
16
19
|
const SubUnitFavorites = ({
|
|
17
20
|
isOwner,
|
|
@@ -25,22 +28,44 @@ const SubUnitFavorites = ({
|
|
|
25
28
|
|
|
26
29
|
useDevicesStatus(unit, favoriteDevices);
|
|
27
30
|
|
|
31
|
+
const favoriteChipIdsSet = useMemo(() => {
|
|
32
|
+
return new Set(favoriteDevices?.map((device) => device.chip_id));
|
|
33
|
+
}, [favoriteDevices]);
|
|
34
|
+
|
|
35
|
+
const { chips, isFetching } = useChipJsonConfiguration({
|
|
36
|
+
dashboardId: unit?.id,
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const listChipsMqtt = useMemo(() => {
|
|
40
|
+
return chips.filter((chip) => favoriteChipIdsSet.has(chip.id));
|
|
41
|
+
}, [chips, favoriteChipIdsSet]);
|
|
42
|
+
|
|
43
|
+
const { mqttConfigs } = useConnectChipMqtt(listChipsMqtt);
|
|
44
|
+
|
|
28
45
|
const configsNeedWatching = useMemo(() => {
|
|
29
46
|
const configIds = [];
|
|
47
|
+
|
|
30
48
|
favoriteDevices.forEach((device) => {
|
|
31
|
-
if (
|
|
32
|
-
device?.quick_action?.config_id &&
|
|
33
|
-
![DEVICE_TYPE.GOOGLE_HOME, DEVICE_TYPE.LG_THINQ].includes(
|
|
34
|
-
device?.device_type
|
|
35
|
-
)
|
|
36
|
-
) {
|
|
49
|
+
if (device?.quick_action?.config_id && device?.is_managed_by_backend) {
|
|
37
50
|
configIds.push(device.quick_action.config_id);
|
|
38
51
|
}
|
|
39
52
|
});
|
|
40
|
-
return configIds;
|
|
41
|
-
}, [favoriteDevices]);
|
|
42
53
|
|
|
43
|
-
|
|
54
|
+
return configIds.filter((id) => !mqttConfigs[id]);
|
|
55
|
+
}, [favoriteDevices, mqttConfigs]);
|
|
56
|
+
|
|
57
|
+
useWatchConfigs(isFetching ? [] : configsNeedWatching);
|
|
58
|
+
|
|
59
|
+
const listSharedChipIds = useMemo(() => {
|
|
60
|
+
const chipMqttIdsSet = new Set(listChipsMqtt.map((chip) => chip.id));
|
|
61
|
+
return [...favoriteChipIdsSet].filter((id) => !chipMqttIdsSet.has(id));
|
|
62
|
+
}, [listChipsMqtt, favoriteChipIdsSet]);
|
|
63
|
+
|
|
64
|
+
useWatchSharedChips({
|
|
65
|
+
dashboardId: unit?.id,
|
|
66
|
+
filterChipIds: listSharedChipIds,
|
|
67
|
+
ready: !!listSharedChipIds.length,
|
|
68
|
+
});
|
|
44
69
|
|
|
45
70
|
const handleOnAddNew = () => {
|
|
46
71
|
navigate(Routes.SelectAddToFavorites, {
|
|
@@ -32,14 +32,17 @@ const ShortDetailSubUnit = ({ unit, station, isOwner }) => {
|
|
|
32
32
|
|
|
33
33
|
useDevicesStatus(unit, station?.devices);
|
|
34
34
|
|
|
35
|
+
const stationChipIdsSet = useMemo(() => {
|
|
36
|
+
return new Set(station?.devices?.map((device) => device.chip_id));
|
|
37
|
+
}, [station?.devices]);
|
|
38
|
+
|
|
35
39
|
const { chips, isFetching } = useChipJsonConfiguration({
|
|
36
40
|
dashboardId: unit?.id,
|
|
37
41
|
});
|
|
38
42
|
|
|
39
43
|
const listChipsMqtt = useMemo(() => {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}, [chips, station?.devices]);
|
|
44
|
+
return chips.filter((chip) => stationChipIdsSet.has(chip.id));
|
|
45
|
+
}, [chips, stationChipIdsSet]);
|
|
43
46
|
|
|
44
47
|
const { mqttConfigs } = useConnectChipMqtt(listChipsMqtt);
|
|
45
48
|
|
|
@@ -64,7 +67,17 @@ const ShortDetailSubUnit = ({ unit, station, isOwner }) => {
|
|
|
64
67
|
}, [station, mqttConfigs]);
|
|
65
68
|
|
|
66
69
|
useWatchConfigs(isFetching ? [] : configsNeedWatching);
|
|
67
|
-
|
|
70
|
+
|
|
71
|
+
const listSharedChipIds = useMemo(() => {
|
|
72
|
+
const chipMqttIdsSet = new Set(listChipsMqtt.map((chip) => chip.id));
|
|
73
|
+
return [...stationChipIdsSet].filter((id) => !chipMqttIdsSet.has(id));
|
|
74
|
+
}, [listChipsMqtt, stationChipIdsSet]);
|
|
75
|
+
|
|
76
|
+
useWatchSharedChips({
|
|
77
|
+
dashboardId: unit?.id,
|
|
78
|
+
filterChipIds: listSharedChipIds,
|
|
79
|
+
ready: !!listSharedChipIds.length,
|
|
80
|
+
});
|
|
68
81
|
|
|
69
82
|
const goToPlayBack = useCallback(() => {
|
|
70
83
|
navigate(Routes.PlaybackCamera, {
|
|
@@ -1,12 +1,21 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import MockAdapter from 'axios-mock-adapter';
|
|
2
3
|
import { act, create } from 'react-test-renderer';
|
|
4
|
+
import { API } from '../../../configs';
|
|
3
5
|
import { SCProvider } from '../../../context';
|
|
4
6
|
import { mockSCStore } from '../../../context/mockStore';
|
|
7
|
+
import { watchMultiDataChips, watchMultiConfigs } from '../../../iot/Monitor';
|
|
8
|
+
import api from '../../../utils/Apis/axios';
|
|
9
|
+
import { gatewayDataFactory } from '../../../utils/FactoryGateway';
|
|
5
10
|
import ItemAddNew from '../../Device/ItemAddNew';
|
|
6
11
|
import ItemDevice from '../../Device/ItemDevice';
|
|
7
12
|
import SubUnitFavorites from '../Favorites';
|
|
8
13
|
import ItemOneTap from '../OneTap/ItemOneTap';
|
|
9
14
|
|
|
15
|
+
const mockAxios = new MockAdapter(api.axiosInstance);
|
|
16
|
+
|
|
17
|
+
jest.mock('../../../iot/Monitor');
|
|
18
|
+
|
|
10
19
|
const wrapComponent = (props) => (
|
|
11
20
|
<SCProvider initState={mockSCStore({})}>
|
|
12
21
|
<SubUnitFavorites {...props} />
|
|
@@ -18,6 +27,7 @@ describe('test ShortDetail Subunit', () => {
|
|
|
18
27
|
let props;
|
|
19
28
|
|
|
20
29
|
beforeEach(() => {
|
|
30
|
+
jest.useFakeTimers();
|
|
21
31
|
props = {
|
|
22
32
|
unit: {
|
|
23
33
|
address: null,
|
|
@@ -78,6 +88,8 @@ describe('test ShortDetail Subunit', () => {
|
|
|
78
88
|
],
|
|
79
89
|
isGGHomeConnected: true,
|
|
80
90
|
};
|
|
91
|
+
watchMultiConfigs.mockClear();
|
|
92
|
+
watchMultiDataChips.mockClear();
|
|
81
93
|
});
|
|
82
94
|
|
|
83
95
|
it('render SubUnitFavorites', async () => {
|
|
@@ -96,4 +108,82 @@ describe('test ShortDetail Subunit', () => {
|
|
|
96
108
|
await itemAddNew[0].props.onAddNew();
|
|
97
109
|
});
|
|
98
110
|
});
|
|
111
|
+
|
|
112
|
+
it('render using mqtt call watch config and data chips', async () => {
|
|
113
|
+
mockAxios
|
|
114
|
+
.onGet(API.CHIP.JSON_CONFIGURATION)
|
|
115
|
+
.reply(200, [gatewayDataFactory]);
|
|
116
|
+
mockAxios
|
|
117
|
+
.onGet(API.CHIP.SHARED_CONFIGURATION)
|
|
118
|
+
.reply(200, [gatewayDataFactory, { ...gatewayDataFactory, id: 7690 }]);
|
|
119
|
+
props.favoriteDevices = [
|
|
120
|
+
{
|
|
121
|
+
action: {
|
|
122
|
+
color: '#00979D',
|
|
123
|
+
icon: 'caretup',
|
|
124
|
+
id: 1,
|
|
125
|
+
key: '',
|
|
126
|
+
},
|
|
127
|
+
action2: null,
|
|
128
|
+
chip_id: 7690,
|
|
129
|
+
description: null,
|
|
130
|
+
icon: '',
|
|
131
|
+
id: 1,
|
|
132
|
+
name: 'People Counting',
|
|
133
|
+
quick_action: { config_id: 128283 },
|
|
134
|
+
remote_control_options: {},
|
|
135
|
+
station: {},
|
|
136
|
+
status: null,
|
|
137
|
+
status2: null,
|
|
138
|
+
is_managed_by_backend: true,
|
|
139
|
+
},
|
|
140
|
+
];
|
|
141
|
+
|
|
142
|
+
await act(async () => {
|
|
143
|
+
tree = await create(wrapComponent(props));
|
|
144
|
+
});
|
|
145
|
+
await act(async () => {
|
|
146
|
+
jest.runOnlyPendingTimers();
|
|
147
|
+
});
|
|
148
|
+
expect(watchMultiConfigs).toHaveBeenCalledWith([128283]);
|
|
149
|
+
expect(watchMultiDataChips).toHaveBeenCalledWith([7690]);
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it('render using mqtt not call watch config and data chips', async () => {
|
|
153
|
+
mockAxios
|
|
154
|
+
.onGet(API.CHIP.JSON_CONFIGURATION)
|
|
155
|
+
.reply(200, [gatewayDataFactory]);
|
|
156
|
+
mockAxios.onGet(API.CHIP.SHARED_CONFIGURATION).reply(200, []);
|
|
157
|
+
props.favoriteDevices = [
|
|
158
|
+
{
|
|
159
|
+
action: {
|
|
160
|
+
color: '#00979D',
|
|
161
|
+
icon: 'caretup',
|
|
162
|
+
id: 1,
|
|
163
|
+
key: '',
|
|
164
|
+
},
|
|
165
|
+
action2: null,
|
|
166
|
+
chip_id: 7689,
|
|
167
|
+
description: null,
|
|
168
|
+
icon: '',
|
|
169
|
+
id: 1,
|
|
170
|
+
name: 'People Counting',
|
|
171
|
+
quick_action: { config_id: 128282 },
|
|
172
|
+
remote_control_options: {},
|
|
173
|
+
station: {},
|
|
174
|
+
status: null,
|
|
175
|
+
status2: null,
|
|
176
|
+
is_managed_by_backend: true,
|
|
177
|
+
},
|
|
178
|
+
];
|
|
179
|
+
|
|
180
|
+
await act(async () => {
|
|
181
|
+
tree = await create(wrapComponent(props));
|
|
182
|
+
});
|
|
183
|
+
await act(async () => {
|
|
184
|
+
jest.runOnlyPendingTimers();
|
|
185
|
+
});
|
|
186
|
+
expect(watchMultiConfigs).not.toHaveBeenCalled();
|
|
187
|
+
expect(watchMultiDataChips).not.toHaveBeenCalled();
|
|
188
|
+
});
|
|
99
189
|
});
|
|
@@ -7,7 +7,7 @@ import { API } from '../../../configs';
|
|
|
7
7
|
import { AccessibilityLabel } from '../../../configs/Constants';
|
|
8
8
|
import { SCProvider } from '../../../context';
|
|
9
9
|
import { mockSCStore } from '../../../context/mockStore';
|
|
10
|
-
import { watchMultiConfigs } from '../../../iot/Monitor';
|
|
10
|
+
import { watchMultiDataChips, watchMultiConfigs } from '../../../iot/Monitor';
|
|
11
11
|
import { keyPermission } from '../../../utils/Permission/common';
|
|
12
12
|
import api from '../../../utils/Apis/axios';
|
|
13
13
|
import Routes from '../../../utils/Route';
|
|
@@ -78,6 +78,7 @@ describe('test ShortDetail Subunit', () => {
|
|
|
78
78
|
isGGHomeConnected: true,
|
|
79
79
|
};
|
|
80
80
|
watchMultiConfigs.mockClear();
|
|
81
|
+
watchMultiDataChips.mockClear();
|
|
81
82
|
});
|
|
82
83
|
|
|
83
84
|
it('render ShortDetail', async () => {
|
|
@@ -191,10 +192,51 @@ describe('test ShortDetail Subunit', () => {
|
|
|
191
192
|
expect(watchMultiConfigs).toHaveBeenCalledWith([1]);
|
|
192
193
|
});
|
|
193
194
|
|
|
194
|
-
it('render using mqtt
|
|
195
|
+
it('render using mqtt call watch config and data chips', async () => {
|
|
195
196
|
mockAxios
|
|
196
197
|
.onGet(API.CHIP.JSON_CONFIGURATION)
|
|
197
198
|
.reply(200, [gatewayDataFactory]);
|
|
199
|
+
mockAxios
|
|
200
|
+
.onGet(API.CHIP.SHARED_CONFIGURATION)
|
|
201
|
+
.reply(200, [gatewayDataFactory, { ...gatewayDataFactory, id: 7690 }]);
|
|
202
|
+
props.station.devices = [
|
|
203
|
+
{
|
|
204
|
+
action: {
|
|
205
|
+
color: '#00979D',
|
|
206
|
+
icon: 'caretup',
|
|
207
|
+
id: 1,
|
|
208
|
+
key: '',
|
|
209
|
+
},
|
|
210
|
+
action2: null,
|
|
211
|
+
chip_id: 7690,
|
|
212
|
+
description: null,
|
|
213
|
+
icon: '',
|
|
214
|
+
id: 1,
|
|
215
|
+
name: 'People Counting',
|
|
216
|
+
quick_action: { config_id: 128283 },
|
|
217
|
+
remote_control_options: {},
|
|
218
|
+
station: {},
|
|
219
|
+
status: null,
|
|
220
|
+
status2: null,
|
|
221
|
+
is_managed_by_backend: true,
|
|
222
|
+
},
|
|
223
|
+
];
|
|
224
|
+
|
|
225
|
+
await act(async () => {
|
|
226
|
+
tree = await create(wrapComponent(props));
|
|
227
|
+
});
|
|
228
|
+
await act(async () => {
|
|
229
|
+
jest.runOnlyPendingTimers();
|
|
230
|
+
});
|
|
231
|
+
expect(watchMultiConfigs).toHaveBeenCalledWith([128283]);
|
|
232
|
+
expect(watchMultiDataChips).toHaveBeenCalledWith([7690]);
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
it('render using mqtt not call watch config and data chips', async () => {
|
|
236
|
+
mockAxios
|
|
237
|
+
.onGet(API.CHIP.JSON_CONFIGURATION)
|
|
238
|
+
.reply(200, [gatewayDataFactory]);
|
|
239
|
+
mockAxios.onGet(API.CHIP.SHARED_CONFIGURATION).reply(200, []);
|
|
198
240
|
props.station.devices = [
|
|
199
241
|
{
|
|
200
242
|
action: {
|
|
@@ -225,6 +267,7 @@ describe('test ShortDetail Subunit', () => {
|
|
|
225
267
|
jest.runOnlyPendingTimers();
|
|
226
268
|
});
|
|
227
269
|
expect(watchMultiConfigs).not.toHaveBeenCalled();
|
|
270
|
+
expect(watchMultiDataChips).not.toHaveBeenCalled();
|
|
228
271
|
});
|
|
229
272
|
|
|
230
273
|
['ConfigAndEvaluation', 'ConfigValue', 'EvaluationOverConfig'].forEach(
|
|
@@ -6,13 +6,17 @@ import { axiosGet } from '../../../utils/Apis/axios';
|
|
|
6
6
|
import { getPusher } from '../../../utils/Pusher';
|
|
7
7
|
|
|
8
8
|
const fetchDataS3 = async (url) => {
|
|
9
|
-
const { data } = await axiosGet(
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
const { data } = await axiosGet(
|
|
10
|
+
url,
|
|
11
|
+
{
|
|
12
|
+
// todo Bang try not to use axiosGet
|
|
13
|
+
transformRequest: (rq, headers) => {
|
|
14
|
+
delete headers.Authorization;
|
|
15
|
+
return rq;
|
|
16
|
+
},
|
|
14
17
|
},
|
|
15
|
-
|
|
18
|
+
true
|
|
19
|
+
);
|
|
16
20
|
return data;
|
|
17
21
|
};
|
|
18
22
|
|
|
@@ -51,9 +55,13 @@ export const useFetchConfigHistory = (
|
|
|
51
55
|
params.append('date_from', date_from.format('YYYY-MM-DDTHH:mm:ss'));
|
|
52
56
|
params.append('date_to', date_to.format('YYYY-MM-DDTHH:mm:ss'));
|
|
53
57
|
|
|
54
|
-
const { success, data } = await axiosGet(
|
|
55
|
-
|
|
56
|
-
|
|
58
|
+
const { success, data } = await axiosGet(
|
|
59
|
+
endpoint,
|
|
60
|
+
{
|
|
61
|
+
params,
|
|
62
|
+
},
|
|
63
|
+
true
|
|
64
|
+
);
|
|
57
65
|
await updateConfigChart(success, data, configs, setChartData);
|
|
58
66
|
setProcessing(false);
|
|
59
67
|
},
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { renderHook } from '@testing-library/react-hooks';
|
|
1
|
+
import { act, renderHook } from '@testing-library/react-hooks';
|
|
3
2
|
import MockAdapter from 'axios-mock-adapter';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { API } from '../../../configs';
|
|
4
5
|
import { SCProvider } from '../../../context';
|
|
5
6
|
import { mockSCStore } from '../../../context/mockStore';
|
|
6
|
-
import { useValueEvaluations } from '../index';
|
|
7
7
|
import api from '../../../utils/Apis/axios';
|
|
8
|
-
import {
|
|
8
|
+
import { useValueEvaluations } from '../index';
|
|
9
9
|
|
|
10
10
|
const mock = new MockAdapter(api.axiosInstance);
|
|
11
11
|
|
|
@@ -35,13 +35,11 @@ describe('Test useValueEvaluation', () => {
|
|
|
35
35
|
it('test unitId not null request success', async () => {
|
|
36
36
|
mock.onGet(API.VALUE_EVALUATIONS()).replyOnce(200, {
|
|
37
37
|
results: [],
|
|
38
|
-
next: 'link',
|
|
39
38
|
});
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
wrapper,
|
|
39
|
+
await act(async () => {
|
|
40
|
+
renderHook(() => useValueEvaluations(1), {
|
|
41
|
+
wrapper,
|
|
42
|
+
});
|
|
45
43
|
});
|
|
46
44
|
expect(mock.history.get.length).toBe(1);
|
|
47
45
|
});
|
|
@@ -50,8 +48,10 @@ describe('Test useValueEvaluation', () => {
|
|
|
50
48
|
mock.onGet(API.VALUE_EVALUATIONS()).replyOnce(400, {
|
|
51
49
|
results: [],
|
|
52
50
|
});
|
|
53
|
-
|
|
54
|
-
|
|
51
|
+
await act(async () => {
|
|
52
|
+
renderHook(() => useValueEvaluations(1), {
|
|
53
|
+
wrapper,
|
|
54
|
+
});
|
|
55
55
|
});
|
|
56
56
|
expect(mock.history.get.length).toBe(1);
|
|
57
57
|
});
|
|
@@ -16,9 +16,13 @@ const useValueEvaluations = (unitId) => {
|
|
|
16
16
|
return;
|
|
17
17
|
}
|
|
18
18
|
const params = { configs__end_device__station__unit: unitId, page: page };
|
|
19
|
-
const { success, data } = await axiosGet(
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
const { success, data } = await axiosGet(
|
|
20
|
+
API.VALUE_EVALUATIONS(),
|
|
21
|
+
{
|
|
22
|
+
params,
|
|
23
|
+
},
|
|
24
|
+
true
|
|
25
|
+
);
|
|
22
26
|
if (success) {
|
|
23
27
|
setAction(Action.UPDATE_VALUE_EVALUATIONS, {
|
|
24
28
|
unitId,
|
|
@@ -60,11 +60,15 @@ const useWatchSharedChips = ({ dashboardId, filterChipIds, ready = true }) => {
|
|
|
60
60
|
return;
|
|
61
61
|
}
|
|
62
62
|
const getGateways = async () => {
|
|
63
|
-
const { success, data } = await axiosGet(
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
const { success, data } = await axiosGet(
|
|
64
|
+
API.CHIP.SHARED_CONFIGURATION,
|
|
65
|
+
{
|
|
66
|
+
params: {
|
|
67
|
+
unit: dashboardId,
|
|
68
|
+
},
|
|
66
69
|
},
|
|
67
|
-
|
|
70
|
+
true
|
|
71
|
+
);
|
|
68
72
|
if (success) {
|
|
69
73
|
setChipIds(data.map((chip) => chip.id));
|
|
70
74
|
handleUpdateConfigsById(data);
|
package/src/hooks/useMqtt.js
CHANGED
|
@@ -34,11 +34,15 @@ const useChipJsonConfiguration = ({ dashboardId, ready = true }) => {
|
|
|
34
34
|
// get chip data
|
|
35
35
|
useEffect(() => {
|
|
36
36
|
const getGateways = async () => {
|
|
37
|
-
const { success, data } = await axiosGet(
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
const { success, data } = await axiosGet(
|
|
38
|
+
API.CHIP.JSON_CONFIGURATION,
|
|
39
|
+
{
|
|
40
|
+
params: {
|
|
41
|
+
unit: dashboardId,
|
|
42
|
+
},
|
|
40
43
|
},
|
|
41
|
-
|
|
44
|
+
true
|
|
45
|
+
);
|
|
42
46
|
if (success) {
|
|
43
47
|
setChips(data);
|
|
44
48
|
handleUpdateConfigsById(data);
|
package/src/iot/UpdateStates.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import moment from 'moment';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { setConfigGlobalState } from './states';
|
|
4
4
|
|
|
5
5
|
const isNewer = (valueTime, valueMicro, currentTime, currentMicro) => {
|
|
6
6
|
if (valueTime?.isAfter(currentTime)) {
|
|
@@ -40,21 +40,42 @@ export const updateGlobalValues = (data) => {
|
|
|
40
40
|
});
|
|
41
41
|
};
|
|
42
42
|
|
|
43
|
+
let pending = {};
|
|
44
|
+
let scheduled = false;
|
|
45
|
+
|
|
43
46
|
export const updateGlobalValue = (configId, value) => {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
if (
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
47
|
+
pending[configId] = value;
|
|
48
|
+
|
|
49
|
+
if (!scheduled) {
|
|
50
|
+
scheduled = true;
|
|
51
|
+
|
|
52
|
+
requestAnimationFrame(() => {
|
|
53
|
+
setConfigGlobalState('configValues', (prev) => {
|
|
54
|
+
let changed = false;
|
|
55
|
+
const next = { ...prev };
|
|
56
|
+
|
|
57
|
+
Object.keys(pending).forEach((id) => {
|
|
58
|
+
const val = pending[id];
|
|
59
|
+
const cur = prev[id];
|
|
60
|
+
|
|
61
|
+
if (
|
|
62
|
+
isNewer(
|
|
63
|
+
val.last_updated,
|
|
64
|
+
val.last_updated_micro,
|
|
65
|
+
cur?.last_updated || moment(0),
|
|
66
|
+
cur?.last_updated_micro || 0
|
|
67
|
+
)
|
|
68
|
+
) {
|
|
69
|
+
next[id] = val;
|
|
70
|
+
changed = true;
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
pending = {};
|
|
75
|
+
scheduled = false;
|
|
76
|
+
|
|
77
|
+
return changed ? next : prev;
|
|
78
|
+
});
|
|
79
|
+
});
|
|
55
80
|
}
|
|
56
|
-
setConfigGlobalState('configValues', {
|
|
57
|
-
...configValues,
|
|
58
|
-
[configId]: value,
|
|
59
|
-
});
|
|
60
81
|
};
|
package/src/iot/mqtt.js
CHANGED
|
@@ -193,6 +193,19 @@ const convert_ai = (bytes_str, config_data = null) => {
|
|
|
193
193
|
);
|
|
194
194
|
};
|
|
195
195
|
|
|
196
|
+
const power_factor_4q_fp_pf = (value) => {
|
|
197
|
+
let pfVal;
|
|
198
|
+
if (value > 1) {
|
|
199
|
+
pfVal = 2 - value;
|
|
200
|
+
} else if (value < -1) {
|
|
201
|
+
pfVal = -2 - value;
|
|
202
|
+
} else {
|
|
203
|
+
pfVal = value;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return pfVal;
|
|
207
|
+
};
|
|
208
|
+
|
|
196
209
|
const mappingTransformer = {
|
|
197
210
|
int_all: int_all,
|
|
198
211
|
float_abcd: float_abcd,
|
|
@@ -224,6 +237,10 @@ const mappingTransformer = {
|
|
|
224
237
|
int_64_cdab: int_64_cdab,
|
|
225
238
|
};
|
|
226
239
|
|
|
240
|
+
const mappingValueConverter = {
|
|
241
|
+
power_factor_4q_fp_pf: power_factor_4q_fp_pf,
|
|
242
|
+
};
|
|
243
|
+
|
|
227
244
|
const extract_config_value = (register, value_bytes) => {
|
|
228
245
|
const transformer = mappingTransformer[register?.transformer];
|
|
229
246
|
if (!transformer) {
|
|
@@ -303,6 +320,11 @@ const get_offset_sample_value = async (value, config) => {
|
|
|
303
320
|
return value;
|
|
304
321
|
};
|
|
305
322
|
|
|
323
|
+
const getValueConverter = (value, config) => {
|
|
324
|
+
const converter = mappingValueConverter[config?.value_converter];
|
|
325
|
+
return converter ? converter(value) : value;
|
|
326
|
+
};
|
|
327
|
+
|
|
306
328
|
const check_filter = (value, config) => {
|
|
307
329
|
if (!config?.active_filter) {
|
|
308
330
|
return false;
|
|
@@ -333,6 +355,7 @@ const updateGlobalValueMqtt = async (config, value, time) => {
|
|
|
333
355
|
|
|
334
356
|
value = get_scale_value(value, config);
|
|
335
357
|
value = await get_offset_sample_value(value, config);
|
|
358
|
+
value = getValueConverter(value, config);
|
|
336
359
|
|
|
337
360
|
if (check_filter(value, config)) {
|
|
338
361
|
return;
|
|
@@ -29,7 +29,11 @@ const AutomateStack = memo(() => {
|
|
|
29
29
|
|
|
30
30
|
useEffect(() => {
|
|
31
31
|
const fetchStarredScripts = async () => {
|
|
32
|
-
const { success, data } = await axiosGet(
|
|
32
|
+
const { success, data } = await axiosGet(
|
|
33
|
+
API.AUTOMATE.STARRED_SCRIPTS(),
|
|
34
|
+
{},
|
|
35
|
+
true
|
|
36
|
+
);
|
|
33
37
|
success && setAction(Action.SET_STARRED_SCRIPTS, data);
|
|
34
38
|
};
|
|
35
39
|
fetchStarredScripts();
|
|
@@ -101,9 +101,13 @@ export default ({ id, type, share, filterEnabled }) => {
|
|
|
101
101
|
}
|
|
102
102
|
params.append('page', page);
|
|
103
103
|
|
|
104
|
-
const { success, data } = await axiosGet(
|
|
105
|
-
|
|
106
|
-
|
|
104
|
+
const { success, data } = await axiosGet(
|
|
105
|
+
api.url(id),
|
|
106
|
+
{
|
|
107
|
+
params: params,
|
|
108
|
+
},
|
|
109
|
+
true
|
|
110
|
+
);
|
|
107
111
|
if (success && data) {
|
|
108
112
|
const { results = [] } = data;
|
|
109
113
|
if (page === 1) {
|
|
@@ -123,7 +127,11 @@ export default ({ id, type, share, filterEnabled }) => {
|
|
|
123
127
|
if (!api?.memberUrl || !filterEnabled?.user) {
|
|
124
128
|
return;
|
|
125
129
|
}
|
|
126
|
-
const { success, data } = await axiosGet(
|
|
130
|
+
const { success, data } = await axiosGet(
|
|
131
|
+
api.memberUrl(share?.id),
|
|
132
|
+
{},
|
|
133
|
+
true
|
|
134
|
+
);
|
|
127
135
|
if (success) {
|
|
128
136
|
data.unshift({ id: 0, name: t('all') });
|
|
129
137
|
setMembers(data);
|
|
@@ -66,7 +66,8 @@ const AddLocationMaps = memo(() => {
|
|
|
66
66
|
|
|
67
67
|
const { success, data } = await axiosGet(
|
|
68
68
|
API.EXTERNAL.GOOGLE_MAP.AUTO_COMPLETE,
|
|
69
|
-
config
|
|
69
|
+
config,
|
|
70
|
+
true
|
|
70
71
|
);
|
|
71
72
|
if (success) {
|
|
72
73
|
setSearchData(data.predictions);
|
|
@@ -103,7 +104,8 @@ const AddLocationMaps = memo(() => {
|
|
|
103
104
|
|
|
104
105
|
const { success, data } = await axiosGet(
|
|
105
106
|
API.EXTERNAL.GOOGLE_MAP.GET_LAT_LNG_BY_PLACE_ID,
|
|
106
|
-
body
|
|
107
|
+
body,
|
|
108
|
+
true
|
|
107
109
|
);
|
|
108
110
|
if (success) {
|
|
109
111
|
const { location } = data.result.geometry;
|
|
@@ -128,7 +130,8 @@ const AddLocationMaps = memo(() => {
|
|
|
128
130
|
latlng: `${currentLatitude},${currentLongitude}`,
|
|
129
131
|
key: SCConfig.GOOGLE_MAP_API_KEY,
|
|
130
132
|
},
|
|
131
|
-
}
|
|
133
|
+
},
|
|
134
|
+
true
|
|
132
135
|
);
|
|
133
136
|
if (success && data.results.length > 0) {
|
|
134
137
|
const result = data.results[0];
|
|
@@ -32,7 +32,11 @@ const ReceiverSelect = ({
|
|
|
32
32
|
);
|
|
33
33
|
|
|
34
34
|
const loadMembers = useCallback(async () => {
|
|
35
|
-
const { success, data } = await axiosGet(
|
|
35
|
+
const { success, data } = await axiosGet(
|
|
36
|
+
API.SHARE.UNITS_MEMBERS(unitId),
|
|
37
|
+
{},
|
|
38
|
+
true
|
|
39
|
+
);
|
|
36
40
|
if (success) {
|
|
37
41
|
setMembers(
|
|
38
42
|
data.map((item) => ({
|