@nordicsemiconductor/pc-nrfconnect-shared 121.0.0 → 122.0.0
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/Changelog.md +34 -0
- package/coverage/cobertura-coverage.xml +1330 -1197
- package/nrfutil/device/__mocks__/device.ts +2 -0
- package/nrfutil/device/batch.ts +18 -2
- package/nrfutil/device/common.ts +17 -38
- package/nrfutil/device/device.ts +2 -0
- package/nrfutil/device/deviceInfo.ts +70 -0
- package/nrfutil/device/erase.ts +2 -2
- package/nrfutil/device/firmwareRead.ts +2 -2
- package/nrfutil/device/getCoreInfo.ts +2 -2
- package/nrfutil/device/getFwInfo.ts +2 -2
- package/nrfutil/device/getProtectionStatus.ts +2 -2
- package/nrfutil/device/list.ts +4 -30
- package/nrfutil/device/program.ts +4 -4
- package/nrfutil/device/recover.ts +2 -2
- package/nrfutil/device/reset.ts +2 -2
- package/nrfutil/device/setMcuState.ts +2 -5
- package/nrfutil/device/setProtectionStatus.ts +2 -2
- package/nrfutil/index.ts +1 -1
- package/nrfutil/moduleVersion.ts +20 -0
- package/nrfutil/sandboxTypes.ts +14 -0
- package/package.json +1 -1
- package/src/About/DeviceCard.tsx +6 -5
- package/src/About/SupportCard.tsx +2 -2
- package/src/Device/DeviceSelector/BasicDeviceInfo.tsx +12 -6
- package/src/Device/DeviceSelector/DeviceList/AnimatedList.tsx +1 -1
- package/src/Device/DeviceSelector/DeviceList/Device.tsx +7 -5
- package/src/Device/DeviceSelector/DeviceList/DeviceList.tsx +23 -5
- package/src/Device/DeviceSelector/DeviceList/EditDeviceButtons.tsx +7 -6
- package/src/Device/DeviceSelector/DeviceList/MoreDeviceInfo.tsx +26 -30
- package/src/Device/DeviceSelector/DeviceList/edit-device-buttons.scss +1 -2
- package/src/Device/DeviceSelector/DeviceSelector.test.tsx +17 -37
- package/src/Device/DeviceSelector/DeviceSelector.tsx +38 -13
- package/src/Device/DeviceSelector/Favorite.tsx +10 -10
- package/src/Device/DeviceSelector/basic-device-info.scss +0 -12
- package/src/Device/deviceInfo/deviceInfo.ts +2 -2
- package/src/Device/deviceLister.ts +52 -43
- package/src/Device/deviceSetup.ts +27 -10
- package/src/Device/deviceSlice.ts +148 -84
- package/src/Device/jprogOperations.ts +56 -27
- package/src/Device/sdfuOperations.ts +25 -31
- package/src/InlineInput/NumberInlineInput.tsx +1 -1
- package/src/InlineInput/NumberInputWithDropdown.tsx +1 -2
- package/src/index.ts +1 -0
- package/src/logging/sendInitialLogMessages.ts +13 -9
- package/src/utils/logLibVersions.ts +1 -1
- package/src/utils/systemReport.ts +3 -3
- package/typings/generated/nrfutil/device/__mocks__/device.d.ts +1 -0
- package/typings/generated/nrfutil/device/__mocks__/device.d.ts.map +1 -1
- package/typings/generated/nrfutil/device/batch.d.ts +3 -2
- package/typings/generated/nrfutil/device/batch.d.ts.map +1 -1
- package/typings/generated/nrfutil/device/common.d.ts +6 -33
- package/typings/generated/nrfutil/device/common.d.ts.map +1 -1
- package/typings/generated/nrfutil/device/device.d.ts +13 -12
- package/typings/generated/nrfutil/device/device.d.ts.map +1 -1
- package/typings/generated/nrfutil/device/deviceInfo.d.ts +40 -0
- package/typings/generated/nrfutil/device/deviceInfo.d.ts.map +1 -0
- package/typings/generated/nrfutil/device/erase.d.ts +2 -2
- package/typings/generated/nrfutil/device/erase.d.ts.map +1 -1
- package/typings/generated/nrfutil/device/firmwareRead.d.ts +2 -2
- package/typings/generated/nrfutil/device/firmwareRead.d.ts.map +1 -1
- package/typings/generated/nrfutil/device/getCoreInfo.d.ts +2 -2
- package/typings/generated/nrfutil/device/getCoreInfo.d.ts.map +1 -1
- package/typings/generated/nrfutil/device/getFwInfo.d.ts +2 -2
- package/typings/generated/nrfutil/device/getFwInfo.d.ts.map +1 -1
- package/typings/generated/nrfutil/device/getProtectionStatus.d.ts +2 -2
- package/typings/generated/nrfutil/device/getProtectionStatus.d.ts.map +1 -1
- package/typings/generated/nrfutil/device/list.d.ts +3 -3
- package/typings/generated/nrfutil/device/list.d.ts.map +1 -1
- package/typings/generated/nrfutil/device/program.d.ts +2 -2
- package/typings/generated/nrfutil/device/program.d.ts.map +1 -1
- package/typings/generated/nrfutil/device/recover.d.ts +2 -2
- package/typings/generated/nrfutil/device/recover.d.ts.map +1 -1
- package/typings/generated/nrfutil/device/reset.d.ts +2 -2
- package/typings/generated/nrfutil/device/reset.d.ts.map +1 -1
- package/typings/generated/nrfutil/device/setMcuState.d.ts +2 -2
- package/typings/generated/nrfutil/device/setMcuState.d.ts.map +1 -1
- package/typings/generated/nrfutil/device/setProtectionStatus.d.ts +2 -2
- package/typings/generated/nrfutil/device/setProtectionStatus.d.ts.map +1 -1
- package/typings/generated/nrfutil/index.d.ts +2 -1
- package/typings/generated/nrfutil/index.d.ts.map +1 -1
- package/typings/generated/nrfutil/moduleVersion.d.ts +4 -0
- package/typings/generated/nrfutil/moduleVersion.d.ts.map +1 -1
- package/typings/generated/nrfutil/sandboxTypes.d.ts +9 -0
- package/typings/generated/nrfutil/sandboxTypes.d.ts.map +1 -1
- package/typings/generated/src/About/DeviceCard.d.ts.map +1 -1
- package/typings/generated/src/Device/DeviceSelector/BasicDeviceInfo.d.ts.map +1 -1
- package/typings/generated/src/Device/DeviceSelector/DeviceList/Device.d.ts +0 -1
- package/typings/generated/src/Device/DeviceSelector/DeviceList/Device.d.ts.map +1 -1
- package/typings/generated/src/Device/DeviceSelector/DeviceList/DeviceList.d.ts.map +1 -1
- package/typings/generated/src/Device/DeviceSelector/DeviceList/EditDeviceButtons.d.ts.map +1 -1
- package/typings/generated/src/Device/DeviceSelector/DeviceList/MoreDeviceInfo.d.ts +0 -1
- package/typings/generated/src/Device/DeviceSelector/DeviceList/MoreDeviceInfo.d.ts.map +1 -1
- package/typings/generated/src/Device/DeviceSelector/DeviceSelector.d.ts.map +1 -1
- package/typings/generated/src/Device/DeviceSelector/Favorite.d.ts +0 -1
- package/typings/generated/src/Device/DeviceSelector/Favorite.d.ts.map +1 -1
- package/typings/generated/src/Device/deviceLister.d.ts +1 -15
- package/typings/generated/src/Device/deviceLister.d.ts.map +1 -1
- package/typings/generated/src/Device/deviceSetup.d.ts +6 -5
- package/typings/generated/src/Device/deviceSetup.d.ts.map +1 -1
- package/typings/generated/src/Device/deviceSlice.d.ts +12 -15
- package/typings/generated/src/Device/deviceSlice.d.ts.map +1 -1
- package/typings/generated/src/Device/jprogOperations.d.ts.map +1 -1
- package/typings/generated/src/Device/sdfuOperations.d.ts.map +1 -1
- package/typings/generated/src/InlineInput/NumberInlineInput.d.ts +1 -1
- package/typings/generated/src/InlineInput/NumberInlineInput.d.ts.map +1 -1
- package/typings/generated/src/InlineInput/NumberInputWithDropdown.d.ts.map +1 -1
- package/typings/generated/src/index.d.ts +1 -1
- package/typings/generated/src/index.d.ts.map +1 -1
- package/typings/generated/src/logging/sendInitialLogMessages.d.ts.map +1 -1
- package/typings/generated/src/utils/systemReport.d.ts +1 -1
- package/typings/generated/src/utils/systemReport.d.ts.map +1 -1
- package/src/Device/DeviceSelector/DeviceList/device.scss +0 -28
- package/src/Device/DeviceSelector/DeviceList/more-device-info.scss +0 -33
- package/src/Device/DeviceSelector/favorite.scss +0 -17
|
@@ -4,11 +4,7 @@
|
|
|
4
4
|
* SPDX-License-Identifier: LicenseRef-Nordic-4-Clause
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import {
|
|
8
|
-
DeviceTraits,
|
|
9
|
-
NrfutilDevice,
|
|
10
|
-
NrfutilDeviceWithSerialnumber,
|
|
11
|
-
} from '../../nrfutil/device/common';
|
|
7
|
+
import { DeviceTraits, NrfutilDevice } from '../../nrfutil/device/common';
|
|
12
8
|
import NrfutilDeviceLib from '../../nrfutil/device/device';
|
|
13
9
|
import logger from '../logging';
|
|
14
10
|
import type { AppThunk, RootState } from '../store';
|
|
@@ -23,7 +19,14 @@ import {
|
|
|
23
19
|
WaitForDevice,
|
|
24
20
|
} from './deviceAutoSelectSlice';
|
|
25
21
|
import { closeDeviceSetupDialog } from './deviceSetupSlice';
|
|
26
|
-
import {
|
|
22
|
+
import {
|
|
23
|
+
addDevice,
|
|
24
|
+
Device,
|
|
25
|
+
getDevice,
|
|
26
|
+
removeDevice,
|
|
27
|
+
selectDevice,
|
|
28
|
+
setSelectedDeviceInfo,
|
|
29
|
+
} from './deviceSlice';
|
|
27
30
|
import { isDeviceInDFUBootloader } from './sdfuOperations';
|
|
28
31
|
|
|
29
32
|
let stopNrfutilDevice: (callback?: () => void) => void;
|
|
@@ -52,6 +55,11 @@ const shouldAutoReselect = (
|
|
|
52
55
|
// device is still connected
|
|
53
56
|
if (disconnectionTime === undefined) return false;
|
|
54
57
|
|
|
58
|
+
// device does not have sn
|
|
59
|
+
if (!addedDevice.serialNumber) {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
|
|
55
63
|
// The device that was selected when disconnection occurred is not yet connected
|
|
56
64
|
if (addedDevice.serialNumber !== autoReselectDevice.serialNumber) {
|
|
57
65
|
return false;
|
|
@@ -100,28 +108,6 @@ const initAutoReconnectTimeout =
|
|
|
100
108
|
);
|
|
101
109
|
};
|
|
102
110
|
|
|
103
|
-
/**
|
|
104
|
-
* Wrap the device form nrfutil-device to make the Device type consistent
|
|
105
|
-
*
|
|
106
|
-
* @param {NrfutilDevice} device The input device from nrfutil-device
|
|
107
|
-
* @returns {NrfutilDevice} The updated device
|
|
108
|
-
*/
|
|
109
|
-
export const wrapDeviceFromNrfdl = (device: NrfutilDevice): Device => ({
|
|
110
|
-
...device,
|
|
111
|
-
boardVersion: device.jlink?.boardVersion ?? undefined,
|
|
112
|
-
serialport: device.serialPorts?.[0] ?? undefined,
|
|
113
|
-
serialNumber: device.serialNumber ?? `fallback-serialnumber-${device.id}`,
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Wrap the device form nrfutil-device to make the Device type consistent
|
|
118
|
-
*
|
|
119
|
-
* @param {NrfutilDevice[]} devices The input devices from nrfutil-device
|
|
120
|
-
* @returns {NrfutilDevice[]} The updated devices
|
|
121
|
-
*/
|
|
122
|
-
export const wrapDevicesFromNrfdl = (devices: NrfutilDevice[]): Device[] =>
|
|
123
|
-
devices.map(wrapDeviceFromNrfdl);
|
|
124
|
-
|
|
125
111
|
export const hasValidDeviceTraits = (
|
|
126
112
|
deviceTraits: DeviceTraits,
|
|
127
113
|
requiredTraits: DeviceTraits
|
|
@@ -144,7 +130,7 @@ const removeDeviceFromList =
|
|
|
144
130
|
(dispatch, getState) => {
|
|
145
131
|
if (
|
|
146
132
|
removedDevice.serialNumber !==
|
|
147
|
-
getState().device.
|
|
133
|
+
getState().device.selectedDevice?.serialNumber
|
|
148
134
|
) {
|
|
149
135
|
dispatch(removeDevice(removedDevice));
|
|
150
136
|
onDeviceDisconnected(removedDevice);
|
|
@@ -176,22 +162,21 @@ export const startWatchingDevices =
|
|
|
176
162
|
doSelectDevice: (device: Device, autoReselected: boolean) => void
|
|
177
163
|
): AppThunk<RootState, void> =>
|
|
178
164
|
(dispatch, getState) => {
|
|
179
|
-
const onDeviceArrived = (device:
|
|
165
|
+
const onDeviceArrived = async (device: NrfutilDevice) => {
|
|
180
166
|
if (hasValidDeviceTraits(device.traits, deviceListing)) {
|
|
181
|
-
device = wrapDeviceFromNrfdl(device);
|
|
182
167
|
if (
|
|
183
168
|
device.serialNumber &&
|
|
184
|
-
!getState().device.devices.
|
|
169
|
+
!getState().device.devices.find(
|
|
170
|
+
d => d.serialNumber === device.serialNumber
|
|
171
|
+
)
|
|
185
172
|
) {
|
|
186
173
|
onDeviceConnected(device);
|
|
187
174
|
}
|
|
188
175
|
|
|
189
|
-
const sn = getState().device.selectedSerialNumber;
|
|
190
176
|
const disconnectionTime =
|
|
191
177
|
getState().deviceAutoSelect.disconnectionTime;
|
|
192
178
|
const autoSelectDevice = getState().deviceAutoSelect.device;
|
|
193
|
-
const selectedDevice =
|
|
194
|
-
sn !== null ? getState().device.devices.get(sn) : undefined;
|
|
179
|
+
const selectedDevice = getState().device.selectedDevice;
|
|
195
180
|
|
|
196
181
|
const result = shouldAutoReselect(
|
|
197
182
|
device,
|
|
@@ -202,17 +187,32 @@ export const startWatchingDevices =
|
|
|
202
187
|
);
|
|
203
188
|
|
|
204
189
|
dispatch(addDevice(device));
|
|
205
|
-
const deviceWithPersistedData = getState().device.devices.
|
|
206
|
-
device.serialNumber
|
|
190
|
+
const deviceWithPersistedData = getState().device.devices.find(
|
|
191
|
+
d => d.serialNumber === device.serialNumber
|
|
207
192
|
);
|
|
208
193
|
|
|
209
194
|
if (!deviceWithPersistedData) return;
|
|
210
195
|
|
|
211
|
-
|
|
196
|
+
// We might get multiple events with the same info so no to trigger auto reconnect multiple times we
|
|
197
|
+
// only do it once per device id
|
|
198
|
+
if (
|
|
199
|
+
result &&
|
|
200
|
+
getState().deviceAutoSelect.lastArrivedDeviceId !==
|
|
201
|
+
deviceWithPersistedData.id
|
|
202
|
+
) {
|
|
203
|
+
dispatch(
|
|
204
|
+
setLastArrivedDeviceId(deviceWithPersistedData.id)
|
|
205
|
+
);
|
|
206
|
+
|
|
207
|
+
const deviceInfo = await NrfutilDeviceLib.deviceInfo(
|
|
208
|
+
device
|
|
209
|
+
);
|
|
210
|
+
|
|
212
211
|
logger.info(
|
|
213
212
|
`Auto Reconnecting Device SN: ${deviceWithPersistedData.serialNumber}`
|
|
214
213
|
);
|
|
215
214
|
doSelectDevice(deviceWithPersistedData, true);
|
|
215
|
+
dispatch(setSelectedDeviceInfo(deviceInfo));
|
|
216
216
|
} else if (
|
|
217
217
|
deviceWithPersistedData.serialNumber ===
|
|
218
218
|
getState().deviceAutoSelect.device?.serialNumber
|
|
@@ -220,6 +220,10 @@ export const startWatchingDevices =
|
|
|
220
220
|
const waitForDevice =
|
|
221
221
|
getState().deviceAutoSelect.waitForDevice;
|
|
222
222
|
|
|
223
|
+
const deviceInfo = await NrfutilDeviceLib.deviceInfo(
|
|
224
|
+
device
|
|
225
|
+
);
|
|
226
|
+
|
|
223
227
|
// Device lib might fail to advertise that a device has left before it rejoins (Mainly OSx)
|
|
224
228
|
// but we still need to trigger the onSuccess if a device 'reappeared' with a different 'id'
|
|
225
229
|
// and there is an outstanding waitForDevice Request. In this case the disconnectionTime was
|
|
@@ -245,8 +249,7 @@ export const startWatchingDevices =
|
|
|
245
249
|
deviceWithPersistedData
|
|
246
250
|
)) ||
|
|
247
251
|
(waitForDevice.when === 'applicationMode' &&
|
|
248
|
-
|
|
249
|
-
null) ||
|
|
252
|
+
deviceInfo?.dfuTriggerVersion) ||
|
|
250
253
|
(selectedDevice &&
|
|
251
254
|
waitForDevice.when === 'sameTraits' &&
|
|
252
255
|
hasSameDeviceTraits(
|
|
@@ -269,6 +272,9 @@ export const startWatchingDevices =
|
|
|
269
272
|
clearWaitForDeviceTimeout(waitForDevice.once)
|
|
270
273
|
);
|
|
271
274
|
|
|
275
|
+
dispatch(selectDevice(deviceWithPersistedData));
|
|
276
|
+
dispatch(setSelectedDeviceInfo(deviceInfo));
|
|
277
|
+
|
|
272
278
|
if (waitForDevice.onSuccess)
|
|
273
279
|
waitForDevice.onSuccess(
|
|
274
280
|
deviceWithPersistedData
|
|
@@ -288,8 +294,9 @@ export const startWatchingDevices =
|
|
|
288
294
|
const waitForDevice =
|
|
289
295
|
getState().deviceAutoSelect.waitForDevice;
|
|
290
296
|
if (
|
|
297
|
+
device.serialNumber &&
|
|
291
298
|
device.serialNumber ===
|
|
292
|
-
|
|
299
|
+
getState().deviceAutoSelect.device?.serialNumber
|
|
293
300
|
) {
|
|
294
301
|
if (waitForDevice) {
|
|
295
302
|
dispatch(setArrivedButWrongWhen(undefined));
|
|
@@ -351,8 +358,10 @@ export const startWatchingDevices =
|
|
|
351
358
|
const autoSelectSN = getAutoSelectDeviceCLISerial();
|
|
352
359
|
|
|
353
360
|
if (autoSelectSN !== undefined) {
|
|
354
|
-
const autoSelectDevice =
|
|
355
|
-
getState()
|
|
361
|
+
const autoSelectDevice = getDevice(
|
|
362
|
+
getState(),
|
|
363
|
+
autoSelectSN
|
|
364
|
+
);
|
|
356
365
|
|
|
357
366
|
if (autoSelectDevice)
|
|
358
367
|
doSelectDevice(autoSelectDevice, true);
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* SPDX-License-Identifier: LicenseRef-Nordic-4-Clause
|
|
5
5
|
*/
|
|
6
|
+
import { DeviceInfo } from '../../nrfutil/device/deviceInfo';
|
|
6
7
|
import logger from '../logging';
|
|
7
8
|
import describeError from '../logging/describeError';
|
|
8
9
|
import { AppThunk, RootState } from '../store';
|
|
@@ -33,15 +34,24 @@ export interface JprogEntry {
|
|
|
33
34
|
}
|
|
34
35
|
|
|
35
36
|
export interface DeviceSetup {
|
|
36
|
-
supportsProgrammingMode: (
|
|
37
|
-
|
|
37
|
+
supportsProgrammingMode: (
|
|
38
|
+
device: Device,
|
|
39
|
+
deviceInfo?: DeviceInfo
|
|
40
|
+
) => boolean; // Return true if this device can be programed using this interface e.g. MCU Boot or DFU
|
|
41
|
+
getFirmwareOptions: (
|
|
42
|
+
device: Device,
|
|
43
|
+
deviceInfo?: DeviceInfo
|
|
44
|
+
) => {
|
|
38
45
|
key: string;
|
|
39
46
|
description?: string;
|
|
40
47
|
programDevice: (
|
|
41
48
|
onProgress: (progress: number, message?: string) => void
|
|
42
49
|
) => AppThunk<RootState, Promise<Device>>;
|
|
43
50
|
}[]; // The list of all firmware that can be applied for this device with the program function for that fw item
|
|
44
|
-
isExpectedFirmware: (
|
|
51
|
+
isExpectedFirmware: (
|
|
52
|
+
device: Device,
|
|
53
|
+
deviceInfo?: DeviceInfo
|
|
54
|
+
) => AppThunk<
|
|
45
55
|
RootState,
|
|
46
56
|
Promise<{
|
|
47
57
|
device: Device;
|
|
@@ -66,6 +76,7 @@ export const prepareDevice =
|
|
|
66
76
|
deviceSetupConfig: DeviceSetupConfig,
|
|
67
77
|
onSuccess: (device: Device) => void,
|
|
68
78
|
onFail: (reason?: unknown) => void,
|
|
79
|
+
deviceInfo: DeviceInfo | undefined,
|
|
69
80
|
checkCurrentFirmwareVersion = true,
|
|
70
81
|
requireUserConfirmation = true
|
|
71
82
|
): AppThunk<RootState, Promise<void>> =>
|
|
@@ -74,18 +85,22 @@ export const prepareDevice =
|
|
|
74
85
|
onSuccess(d);
|
|
75
86
|
dispatch(closeDeviceSetupDialog());
|
|
76
87
|
};
|
|
88
|
+
|
|
77
89
|
const validDeviceSetups = deviceSetupConfig.deviceSetups.filter(
|
|
78
|
-
deviceSetup =>
|
|
90
|
+
deviceSetup =>
|
|
91
|
+
deviceSetup.supportsProgrammingMode(device, deviceInfo)
|
|
79
92
|
);
|
|
80
93
|
|
|
81
94
|
const possibleFirmware = validDeviceSetups
|
|
82
|
-
.map(deviceSetup =>
|
|
95
|
+
.map(deviceSetup =>
|
|
96
|
+
deviceSetup.getFirmwareOptions(device, deviceInfo)
|
|
97
|
+
)
|
|
83
98
|
.flat();
|
|
84
99
|
|
|
85
100
|
if (possibleFirmware.length === 0) {
|
|
86
101
|
logger.info(
|
|
87
102
|
`Connected to device with serial number: ${device.serialNumber} ` +
|
|
88
|
-
`and family: ${device.
|
|
103
|
+
`and family: ${device.devkit?.deviceFamily || 'Unknown'} `
|
|
89
104
|
);
|
|
90
105
|
if (deviceSetupConfig.allowCustomDevice) {
|
|
91
106
|
logger.info(
|
|
@@ -110,7 +125,7 @@ export const prepareDevice =
|
|
|
110
125
|
try {
|
|
111
126
|
// eslint-disable-next-line no-await-in-loop
|
|
112
127
|
const result = await dispatch(
|
|
113
|
-
deviceSetup.isExpectedFirmware(device)
|
|
128
|
+
deviceSetup.isExpectedFirmware(device, deviceInfo)
|
|
114
129
|
);
|
|
115
130
|
device = result.device;
|
|
116
131
|
if (result.validFirmware) {
|
|
@@ -227,7 +242,8 @@ export const setupDevice =
|
|
|
227
242
|
device: Device,
|
|
228
243
|
deviceSetupConfig: DeviceSetupConfig,
|
|
229
244
|
onDeviceIsReady: (device: Device) => void,
|
|
230
|
-
doDeselectDevice: () => void
|
|
245
|
+
doDeselectDevice: () => void,
|
|
246
|
+
deviceInfo: DeviceInfo | undefined
|
|
231
247
|
): AppThunk<RootState> =>
|
|
232
248
|
(dispatch, getState) =>
|
|
233
249
|
dispatch(
|
|
@@ -242,7 +258,7 @@ export const setupDevice =
|
|
|
242
258
|
// while that is still in progress select some other device
|
|
243
259
|
// if both were to call onDeviceIsReady the app might have unexpected side effects
|
|
244
260
|
if (
|
|
245
|
-
getState().device.
|
|
261
|
+
getState().device.selectedDevice?.serialNumber ===
|
|
246
262
|
d.serialNumber
|
|
247
263
|
) {
|
|
248
264
|
onDeviceIsReady(d);
|
|
@@ -255,6 +271,7 @@ export const setupDevice =
|
|
|
255
271
|
);
|
|
256
272
|
logger.error(describeError(error));
|
|
257
273
|
doDeselectDevice();
|
|
258
|
-
}
|
|
274
|
+
},
|
|
275
|
+
deviceInfo
|
|
259
276
|
)
|
|
260
277
|
);
|
|
@@ -8,7 +8,8 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit';
|
|
|
8
8
|
import type { AutoDetectTypes } from '@serialport/bindings-cpp';
|
|
9
9
|
import { SerialPortOpenOptions } from 'serialport';
|
|
10
10
|
|
|
11
|
-
import {
|
|
11
|
+
import { DeviceInfo } from '../../nrfutil';
|
|
12
|
+
import { NrfutilDevice } from '../../nrfutil/device/common';
|
|
12
13
|
import type { RootState } from '../store';
|
|
13
14
|
import {
|
|
14
15
|
getPersistedIsFavorite,
|
|
@@ -20,65 +21,74 @@ import {
|
|
|
20
21
|
} from '../utils/persistentStore';
|
|
21
22
|
|
|
22
23
|
export interface Device extends NrfutilDevice {
|
|
23
|
-
serialNumber: string;
|
|
24
|
-
boardVersion?: string;
|
|
25
24
|
nickname?: string;
|
|
26
|
-
serialport?: SerialPort;
|
|
27
25
|
favorite?: boolean;
|
|
28
|
-
id: number;
|
|
29
26
|
persistedSerialPortOptions?: SerialPortOpenOptions<AutoDetectTypes>;
|
|
30
27
|
}
|
|
31
28
|
|
|
29
|
+
const findDeviceItem = (
|
|
30
|
+
devices: Device[],
|
|
31
|
+
id: number,
|
|
32
|
+
serialNumber?: string
|
|
33
|
+
) => {
|
|
34
|
+
const index = devices.findIndex(
|
|
35
|
+
d => d.id === id || d.serialNumber === serialNumber
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
return { index, device: devices[index] };
|
|
39
|
+
};
|
|
40
|
+
|
|
32
41
|
const updateDevice = (
|
|
33
42
|
state: DeviceState,
|
|
34
|
-
|
|
35
|
-
|
|
43
|
+
updateToMergeIn: Partial<Device>,
|
|
44
|
+
id: number,
|
|
45
|
+
serialNumber?: string
|
|
36
46
|
) => {
|
|
37
|
-
const device = state.devices
|
|
47
|
+
const device = findDeviceItem(state.devices, id, serialNumber).device;
|
|
38
48
|
if (device) {
|
|
39
49
|
Object.assign(device, updateToMergeIn);
|
|
40
50
|
}
|
|
41
51
|
};
|
|
42
52
|
|
|
43
53
|
export interface DeviceState {
|
|
44
|
-
devices:
|
|
45
|
-
deviceInfo: Device | null;
|
|
46
|
-
selectedSerialNumber: string | null;
|
|
54
|
+
devices: Device[];
|
|
47
55
|
readbackProtection: 'unknown' | 'protected' | 'unprotected';
|
|
56
|
+
selectedDevice?: Device;
|
|
57
|
+
selectedDeviceInfo?: DeviceInfo;
|
|
48
58
|
}
|
|
49
59
|
|
|
50
60
|
const initialState: DeviceState = {
|
|
51
|
-
devices:
|
|
52
|
-
selectedSerialNumber: null,
|
|
53
|
-
deviceInfo: null,
|
|
61
|
+
devices: [],
|
|
54
62
|
readbackProtection: 'unknown',
|
|
55
63
|
};
|
|
56
64
|
|
|
57
65
|
const setPersistedData = (device: Device) => {
|
|
58
|
-
|
|
59
|
-
...device
|
|
60
|
-
favorite
|
|
61
|
-
nickname
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
66
|
+
if (device.serialNumber) {
|
|
67
|
+
const newDevice = { ...device };
|
|
68
|
+
newDevice.favorite = getPersistedIsFavorite(device.serialNumber);
|
|
69
|
+
newDevice.nickname = getPersistedNickname(device.serialNumber);
|
|
70
|
+
|
|
71
|
+
const persistedSerialPortSettings = getPersistedSerialPortSettings(
|
|
72
|
+
device.serialNumber
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
if (persistedSerialPortSettings) {
|
|
76
|
+
const path =
|
|
77
|
+
newDevice.serialPorts?.[persistedSerialPortSettings.vComIndex]
|
|
78
|
+
?.comName;
|
|
79
|
+
|
|
80
|
+
if (path) {
|
|
81
|
+
newDevice.persistedSerialPortOptions = {
|
|
82
|
+
...persistedSerialPortSettings.serialPortOptions,
|
|
83
|
+
path,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
78
86
|
}
|
|
87
|
+
|
|
88
|
+
return newDevice;
|
|
79
89
|
}
|
|
80
90
|
|
|
81
|
-
return
|
|
91
|
+
return device;
|
|
82
92
|
};
|
|
83
93
|
|
|
84
94
|
const slice = createSlice({
|
|
@@ -89,104 +99,158 @@ const slice = createSlice({
|
|
|
89
99
|
* Indicates that a device has been selected.
|
|
90
100
|
*/
|
|
91
101
|
selectDevice: (state, action: PayloadAction<Device>) => {
|
|
92
|
-
state.
|
|
102
|
+
state.selectedDevice = action.payload;
|
|
103
|
+
},
|
|
104
|
+
|
|
105
|
+
setSelectedDeviceInfo: (
|
|
106
|
+
state,
|
|
107
|
+
action: PayloadAction<DeviceInfo | undefined>
|
|
108
|
+
) => {
|
|
109
|
+
state.selectedDeviceInfo = action.payload;
|
|
93
110
|
},
|
|
94
111
|
|
|
95
112
|
/*
|
|
96
113
|
* Indicates that the currently selected device has been deselected.
|
|
97
114
|
*/
|
|
98
115
|
deselectDevice: state => {
|
|
99
|
-
state.
|
|
100
|
-
state.
|
|
116
|
+
state.selectedDevice = undefined;
|
|
117
|
+
state.selectedDeviceInfo = undefined;
|
|
101
118
|
state.readbackProtection = 'unknown';
|
|
102
119
|
},
|
|
103
120
|
|
|
104
121
|
addDevice: (state, action: PayloadAction<Device>) => {
|
|
105
|
-
state.devices.
|
|
106
|
-
|
|
107
|
-
|
|
122
|
+
const index = state.devices.findIndex(
|
|
123
|
+
item =>
|
|
124
|
+
item.serialNumber === action.payload.serialNumber ||
|
|
125
|
+
item.id === action.payload.id
|
|
108
126
|
);
|
|
127
|
+
|
|
128
|
+
const device = setPersistedData(action.payload);
|
|
129
|
+
if (index !== -1) {
|
|
130
|
+
state.devices[index] = device;
|
|
131
|
+
} else {
|
|
132
|
+
state.devices.push(device);
|
|
133
|
+
}
|
|
109
134
|
},
|
|
110
135
|
|
|
111
136
|
persistSerialPortOptions: (
|
|
112
137
|
state,
|
|
113
138
|
action: PayloadAction<SerialPortOpenOptions<AutoDetectTypes>>
|
|
114
139
|
) => {
|
|
115
|
-
if (state.
|
|
140
|
+
if (!state.selectedDevice) return;
|
|
116
141
|
|
|
117
|
-
const selectedDevice = state.
|
|
118
|
-
state.selectedSerialNumber
|
|
119
|
-
);
|
|
142
|
+
const selectedDevice = state.selectedDevice;
|
|
120
143
|
|
|
121
144
|
if (selectedDevice) {
|
|
122
145
|
const vComIndex = selectedDevice.serialPorts?.findIndex(
|
|
123
146
|
e => e.comName === action.payload.path
|
|
124
147
|
);
|
|
125
148
|
|
|
126
|
-
if (
|
|
149
|
+
if (
|
|
150
|
+
selectedDevice.serialNumber &&
|
|
151
|
+
vComIndex !== undefined &&
|
|
152
|
+
vComIndex !== -1
|
|
153
|
+
) {
|
|
127
154
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- used to filter out the path property
|
|
128
155
|
const { path: _, ...serialPortOptions } = action.payload;
|
|
129
156
|
|
|
130
157
|
persistSerialPortSettingsToStore(
|
|
131
|
-
|
|
158
|
+
selectedDevice.serialNumber,
|
|
132
159
|
{
|
|
133
160
|
serialPortOptions,
|
|
134
161
|
vComIndex,
|
|
135
162
|
}
|
|
136
163
|
);
|
|
137
164
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
165
|
+
updateDevice(
|
|
166
|
+
state,
|
|
167
|
+
{
|
|
168
|
+
...selectedDevice,
|
|
169
|
+
persistedSerialPortOptions: action.payload,
|
|
170
|
+
},
|
|
171
|
+
selectedDevice.id,
|
|
172
|
+
selectedDevice.serialNumber
|
|
173
|
+
);
|
|
142
174
|
}
|
|
143
175
|
}
|
|
144
176
|
},
|
|
145
177
|
|
|
146
178
|
removeDevice: (state, action: PayloadAction<Device>) => {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
179
|
+
const index = findDeviceItem(
|
|
180
|
+
state.devices,
|
|
181
|
+
action.payload.id,
|
|
182
|
+
action.payload.serialNumber
|
|
183
|
+
).index;
|
|
184
|
+
state.devices.splice(index, 1);
|
|
185
|
+
|
|
186
|
+
if (action.payload.id === state.selectedDevice?.id) {
|
|
187
|
+
state.selectedDevice = undefined;
|
|
188
|
+
state.selectedDeviceInfo = undefined;
|
|
152
189
|
}
|
|
153
190
|
},
|
|
154
191
|
|
|
155
|
-
toggleDeviceFavorited: (state, action: PayloadAction<
|
|
156
|
-
const
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
192
|
+
toggleDeviceFavorited: (state, action: PayloadAction<Device>) => {
|
|
193
|
+
const device = findDeviceItem(
|
|
194
|
+
state.devices,
|
|
195
|
+
action.payload.id,
|
|
196
|
+
action.payload.serialNumber
|
|
197
|
+
).device;
|
|
198
|
+
|
|
199
|
+
if (!device.serialNumber) return;
|
|
200
|
+
|
|
201
|
+
const newFavoriteState = !device.favorite;
|
|
202
|
+
|
|
203
|
+
persistIsFavorite(device.serialNumber, newFavoriteState);
|
|
204
|
+
updateDevice(
|
|
205
|
+
state,
|
|
206
|
+
{
|
|
207
|
+
favorite: newFavoriteState,
|
|
208
|
+
},
|
|
209
|
+
action.payload.id,
|
|
210
|
+
action.payload.serialNumber
|
|
211
|
+
);
|
|
162
212
|
},
|
|
163
213
|
|
|
164
214
|
setDeviceNickname: {
|
|
165
|
-
prepare: (
|
|
166
|
-
payload: {
|
|
215
|
+
prepare: (device: Device, nickname: string) => ({
|
|
216
|
+
payload: { device, nickname },
|
|
167
217
|
}),
|
|
168
218
|
reducer: (
|
|
169
219
|
state,
|
|
170
220
|
action: PayloadAction<{
|
|
171
|
-
|
|
221
|
+
device: Device;
|
|
172
222
|
nickname: string;
|
|
173
223
|
}>
|
|
174
224
|
) => {
|
|
225
|
+
if (!action.payload.device.serialNumber) return;
|
|
226
|
+
|
|
175
227
|
persistNickname(
|
|
176
|
-
action.payload.serialNumber,
|
|
228
|
+
action.payload.device.serialNumber,
|
|
177
229
|
action.payload.nickname
|
|
178
230
|
);
|
|
179
|
-
updateDevice(
|
|
180
|
-
|
|
181
|
-
|
|
231
|
+
updateDevice(
|
|
232
|
+
state,
|
|
233
|
+
{
|
|
234
|
+
nickname: action.payload.nickname,
|
|
235
|
+
},
|
|
236
|
+
action.payload.device.id,
|
|
237
|
+
action.payload.device.serialNumber
|
|
238
|
+
);
|
|
182
239
|
},
|
|
183
240
|
},
|
|
184
241
|
|
|
185
|
-
resetDeviceNickname: (state, action: PayloadAction<
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
242
|
+
resetDeviceNickname: (state, action: PayloadAction<Device>) => {
|
|
243
|
+
if (!action.payload.serialNumber) return;
|
|
244
|
+
|
|
245
|
+
persistNickname(action.payload.serialNumber, '');
|
|
246
|
+
updateDevice(
|
|
247
|
+
state,
|
|
248
|
+
{
|
|
249
|
+
nickname: '',
|
|
250
|
+
},
|
|
251
|
+
action.payload.id,
|
|
252
|
+
action.payload.serialNumber
|
|
253
|
+
);
|
|
190
254
|
},
|
|
191
255
|
|
|
192
256
|
setReadbackProtected: (
|
|
@@ -204,6 +268,7 @@ export const {
|
|
|
204
268
|
deselectDevice,
|
|
205
269
|
resetDeviceNickname,
|
|
206
270
|
selectDevice,
|
|
271
|
+
setSelectedDeviceInfo,
|
|
207
272
|
addDevice,
|
|
208
273
|
removeDevice,
|
|
209
274
|
setDeviceNickname,
|
|
@@ -213,22 +278,21 @@ export const {
|
|
|
213
278
|
},
|
|
214
279
|
} = slice;
|
|
215
280
|
|
|
216
|
-
export const getDevice = (
|
|
217
|
-
state.device.devices.
|
|
281
|
+
export const getDevice = (state: RootState, serialNumber: string) =>
|
|
282
|
+
state.device.devices.find(d => d.serialNumber === serialNumber);
|
|
218
283
|
|
|
219
284
|
export const getDevices = (state: RootState) => state.device.devices;
|
|
220
285
|
|
|
221
286
|
export const deviceIsSelected = (state: RootState) =>
|
|
222
|
-
state.device.
|
|
287
|
+
!!state.device.selectedDevice;
|
|
288
|
+
|
|
289
|
+
export const selectedDevice = (state: RootState) => state.device.selectedDevice;
|
|
223
290
|
|
|
224
|
-
export const
|
|
225
|
-
state.device.
|
|
226
|
-
? state.device.devices.get(state.device.selectedSerialNumber)
|
|
227
|
-
: undefined;
|
|
291
|
+
export const selectedDeviceInfo = (state: RootState) =>
|
|
292
|
+
state.device.selectedDevice ? state.device.selectedDeviceInfo : undefined;
|
|
228
293
|
|
|
229
|
-
export const deviceInfo = (state: RootState) => state.device.deviceInfo;
|
|
230
294
|
export const selectedSerialNumber = (state: RootState) =>
|
|
231
|
-
state.device.
|
|
295
|
+
state.device.selectedDevice?.serialNumber;
|
|
232
296
|
|
|
233
297
|
export const getReadbackProtection = (state: RootState) =>
|
|
234
298
|
state.device.readbackProtection;
|