@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.
Files changed (53) hide show
  1. package/package.json +1 -1
  2. package/src/commons/Dashboard/MyDashboardDevice/index.js +14 -12
  3. package/src/commons/Dashboard/MyUnit/index.js +4 -3
  4. package/src/commons/DateTimeRangeChange/index.js +5 -5
  5. package/src/commons/Device/HorizontalBarChart.js +11 -24
  6. package/src/commons/Device/PowerConsumptionChart.js +195 -103
  7. package/src/commons/FieldTemplate/ChooseUserField/index.js +5 -1
  8. package/src/commons/Form/CurrencyInput.js +9 -18
  9. package/src/commons/SelectGateway/index.js +2 -1
  10. package/src/commons/SelectSubUnit/index.js +5 -1
  11. package/src/commons/SelectUnit/index.js +1 -1
  12. package/src/commons/SubUnit/Favorites/index.js +35 -10
  13. package/src/commons/SubUnit/ShortDetail.js +17 -4
  14. package/src/commons/SubUnit/__test__/Favorites.test.js +90 -0
  15. package/src/commons/SubUnit/__test__/ShortDetail.test.js +45 -2
  16. package/src/commons/UnitSummary/ConfigHistoryChart/index.js +17 -9
  17. package/src/hooks/IoT/__test__/useValueEvaluation.test.js +12 -12
  18. package/src/hooks/IoT/useValueEvaluation.js +7 -3
  19. package/src/hooks/IoT/useWatchSharedChips.js +8 -4
  20. package/src/hooks/useMqtt.js +8 -4
  21. package/src/iot/UpdateStates.js +37 -16
  22. package/src/iot/mqtt.js +23 -0
  23. package/src/navigations/AutomateStack.js +5 -1
  24. package/src/screens/ActivityLog/hooks/index.js +12 -4
  25. package/src/screens/AddLocationMaps/index.js +6 -3
  26. package/src/screens/AddNewGateway/RenameNewDevices.js +2 -1
  27. package/src/screens/Automate/AddNewAction/ChooseConfig.js +2 -1
  28. package/src/screens/Automate/AddNewAction/ReceiverSelect.js +5 -1
  29. package/src/screens/Automate/MultiUnits.js +2 -1
  30. package/src/screens/Automate/ScriptDetail/index.js +11 -3
  31. package/src/screens/Automate/hooks/useAction.js +3 -1
  32. package/src/screens/Device/__test__/DeviceDetail-3rdparty.test.js +16 -5
  33. package/src/screens/Device/__test__/DeviceDetail-arduino.test.js +10 -0
  34. package/src/screens/Device/__test__/DeviceDetail-modbus.test.js +37 -8
  35. package/src/screens/Device/__test__/DeviceDetail-zigbee.test.js +16 -5
  36. package/src/screens/Device/__test__/DeviceDetail.test.js +17 -6
  37. package/src/screens/Device/__test__/sensorDisplayItem.test.js +47 -11
  38. package/src/screens/Device/components/SensorDisplayItem.js +23 -5
  39. package/src/screens/Device/detail.js +10 -3
  40. package/src/screens/Device/hooks/useEvaluateValue.js +7 -3
  41. package/src/screens/Device/styles.js +4 -0
  42. package/src/screens/SelectUnit/index.js +3 -1
  43. package/src/screens/Sharing/InfoMemberUnit.js +3 -1
  44. package/src/screens/SideMenuDetail/index.js +3 -1
  45. package/src/screens/Unit/SelectAddToFavorites.js +6 -2
  46. package/src/screens/UnitSummary/components/3PPowerConsumption/index.js +8 -48
  47. package/src/screens/UnitSummary/components/PowerConsumption/__test__/PowerConsumption.test.js +121 -6
  48. package/src/screens/UnitSummary/components/PowerConsumption/index.js +6 -46
  49. package/src/screens/UnitSummary/index.js +2 -1
  50. package/src/utils/I18n/translations/en.js +1 -0
  51. package/src/utils/I18n/translations/vi.js +1 -0
  52. package/src/utils/chartHelper/index.js +53 -0
  53. 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
- useWatchConfigs(configsNeedWatching);
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
- const stationChipIds = station?.devices?.map((device) => device.chip_id);
41
- return chips?.filter((chip) => stationChipIds?.includes(chip.id));
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
- useWatchSharedChips({ dashboardId: unit?.id });
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 not call watch config', async () => {
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(url, {
10
- // todo Bang try not to use axiosGet
11
- transformRequest: (rq, headers) => {
12
- delete headers.Authorization;
13
- return rq;
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(endpoint, {
55
- params,
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 React from 'react';
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 { API } from '../../../configs';
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
- mock.onGet(API.VALUE_EVALUATIONS()).replyOnce(200, {
41
- results: [],
42
- });
43
- renderHook(() => useValueEvaluations(1), {
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
- renderHook(() => useValueEvaluations(1), {
54
- wrapper,
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(API.VALUE_EVALUATIONS(), {
20
- params,
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(API.CHIP.SHARED_CONFIGURATION, {
64
- params: {
65
- unit: dashboardId,
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);
@@ -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(API.CHIP.JSON_CONFIGURATION, {
38
- params: {
39
- unit: dashboardId,
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);
@@ -1,6 +1,6 @@
1
1
  import moment from 'moment';
2
2
 
3
- import { getConfigGlobalState, setConfigGlobalState } from './states';
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
- const configValues = getConfigGlobalState('configValues');
45
- const currentValue = configValues[configId];
46
- if (
47
- !isNewer(
48
- value.last_updated,
49
- value.last_updated_micro,
50
- currentValue?.last_updated || moment(0),
51
- currentValue?.last_updated_micro || 0
52
- )
53
- ) {
54
- return;
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(API.AUTOMATE.STARRED_SCRIPTS());
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(api.url(id), {
105
- params: params,
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(api.memberUrl(share?.id));
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];
@@ -168,7 +168,8 @@ const RenameNewDevices = memo(({ route }) => {
168
168
  API.CHIP.RENAME_DEVICES(chipId),
169
169
  {
170
170
  params,
171
- }
171
+ },
172
+ true
172
173
  );
173
174
  if (success) {
174
175
  setInfo(data);
@@ -27,7 +27,8 @@ const ChooseConfig = ({ route }) => {
27
27
 
28
28
  const { success, data: automateData } = await axiosGet(
29
29
  API.AUTOMATE.DISPLAY_CONFIGS(device.id),
30
- { params }
30
+ { params },
31
+ true
31
32
  );
32
33
 
33
34
  if (success) {
@@ -32,7 +32,11 @@ const ReceiverSelect = ({
32
32
  );
33
33
 
34
34
  const loadMembers = useCallback(async () => {
35
- const { success, data } = await axiosGet(API.SHARE.UNITS_MEMBERS(unitId));
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) => ({