@nordicsemiconductor/pc-nrfconnect-shared 121.0.0 → 123.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.
Files changed (174) hide show
  1. package/Changelog.md +85 -0
  2. package/coverage/cobertura-coverage.xml +2276 -1778
  3. package/ipc/launcherConfig.ts +25 -0
  4. package/ipc/openWindow.ts +17 -1
  5. package/ipc/schema/packageJson.ts +26 -22
  6. package/main/index.ts +11 -5
  7. package/mocks/packageJsonMock.ts +1 -1
  8. package/nrfutil/device/__mocks__/device.ts +2 -0
  9. package/nrfutil/device/batch.ts +19 -9
  10. package/nrfutil/device/common.ts +32 -46
  11. package/nrfutil/device/device.ts +2 -0
  12. package/nrfutil/device/deviceInfo.ts +70 -0
  13. package/nrfutil/device/erase.ts +2 -2
  14. package/nrfutil/device/firmwareRead.ts +2 -2
  15. package/nrfutil/device/getCoreInfo.ts +2 -2
  16. package/nrfutil/device/getFwInfo.ts +2 -2
  17. package/nrfutil/device/getProtectionStatus.ts +2 -2
  18. package/nrfutil/device/list.ts +5 -31
  19. package/nrfutil/device/program.ts +4 -4
  20. package/nrfutil/device/recover.ts +2 -2
  21. package/nrfutil/device/reset.ts +2 -2
  22. package/nrfutil/device/setMcuState.ts +2 -5
  23. package/nrfutil/device/setProtectionStatus.ts +2 -2
  24. package/nrfutil/index.ts +1 -1
  25. package/nrfutil/moduleVersion.ts +22 -2
  26. package/nrfutil/sandbox.ts +52 -32
  27. package/nrfutil/sandboxTypes.ts +15 -1
  28. package/package.json +3 -2
  29. package/scripts/check-app-properties.ts +6 -6
  30. package/scripts/esbuild.ts +3 -3
  31. package/scripts/nordic-publish.js +23 -23
  32. package/scripts/nordic-publish.ts +3 -3
  33. package/scripts/release-shared.ts +2 -2
  34. package/src/About/ApplicationCard.tsx +3 -5
  35. package/src/About/DeviceCard.tsx +6 -5
  36. package/src/About/SupportCard.tsx +2 -2
  37. package/src/App/App.test.tsx +7 -0
  38. package/src/App/App.tsx +14 -27
  39. package/src/Device/DeviceSelector/BasicDeviceInfo.tsx +12 -6
  40. package/src/Device/DeviceSelector/DeviceList/AnimatedList.tsx +1 -1
  41. package/src/Device/DeviceSelector/DeviceList/Device.tsx +7 -5
  42. package/src/Device/DeviceSelector/DeviceList/DeviceList.tsx +23 -5
  43. package/src/Device/DeviceSelector/DeviceList/EditDeviceButtons.tsx +7 -6
  44. package/src/Device/DeviceSelector/DeviceList/MoreDeviceInfo.tsx +26 -30
  45. package/src/Device/DeviceSelector/DeviceList/edit-device-buttons.scss +1 -2
  46. package/src/Device/DeviceSelector/DeviceSelector.test.tsx +17 -37
  47. package/src/Device/DeviceSelector/DeviceSelector.tsx +64 -21
  48. package/src/Device/DeviceSelector/Favorite.tsx +10 -10
  49. package/src/Device/DeviceSelector/basic-device-info.scss +0 -12
  50. package/src/Device/deviceInfo/deviceInfo.ts +2 -2
  51. package/src/Device/deviceLister.ts +111 -59
  52. package/src/Device/deviceSetup.ts +30 -13
  53. package/src/Device/deviceSlice.ts +157 -84
  54. package/src/Device/jprogOperations.ts +56 -27
  55. package/src/Device/sdfuOperations.ts +25 -31
  56. package/src/ErrorBoundary/ErrorBoundary.tsx +7 -13
  57. package/src/Feedback/sendFeedback.ts +2 -4
  58. package/src/InlineInput/NumberInlineInput.tsx +1 -1
  59. package/src/InlineInput/NumberInputWithDropdown.tsx +1 -2
  60. package/src/index.ts +4 -0
  61. package/src/logging/sendInitialLogMessages.ts +15 -13
  62. package/src/utils/appDetails.ts +22 -0
  63. package/src/utils/appDirs.ts +4 -4
  64. package/src/utils/launcherConfig.ts +17 -0
  65. package/src/utils/logLibVersions.ts +1 -1
  66. package/src/utils/packageJson.ts +52 -10
  67. package/src/utils/persistentStore.ts +21 -14
  68. package/src/utils/systemReport.ts +4 -6
  69. package/src/utils/usageData.ts +75 -167
  70. package/src/utils/usageDataCommon.ts +59 -0
  71. package/src/utils/usageDataMain.ts +117 -0
  72. package/src/utils/usageDataRenderer.ts +126 -0
  73. package/src/utils/useHotKey.ts +2 -2
  74. package/typings/generated/ipc/launcherConfig.d.ts +14 -0
  75. package/typings/generated/ipc/launcherConfig.d.ts.map +1 -0
  76. package/typings/generated/ipc/openWindow.d.ts +10 -4
  77. package/typings/generated/ipc/openWindow.d.ts.map +1 -1
  78. package/typings/generated/ipc/schema/packageJson.d.ts +34 -52
  79. package/typings/generated/ipc/schema/packageJson.d.ts.map +1 -1
  80. package/typings/generated/main/index.d.ts +8 -2
  81. package/typings/generated/main/index.d.ts.map +1 -1
  82. package/typings/generated/nrfutil/device/__mocks__/device.d.ts +1 -0
  83. package/typings/generated/nrfutil/device/__mocks__/device.d.ts.map +1 -1
  84. package/typings/generated/nrfutil/device/batch.d.ts +3 -2
  85. package/typings/generated/nrfutil/device/batch.d.ts.map +1 -1
  86. package/typings/generated/nrfutil/device/common.d.ts +7 -34
  87. package/typings/generated/nrfutil/device/common.d.ts.map +1 -1
  88. package/typings/generated/nrfutil/device/device.d.ts +14 -13
  89. package/typings/generated/nrfutil/device/device.d.ts.map +1 -1
  90. package/typings/generated/nrfutil/device/deviceInfo.d.ts +40 -0
  91. package/typings/generated/nrfutil/device/deviceInfo.d.ts.map +1 -0
  92. package/typings/generated/nrfutil/device/erase.d.ts +2 -2
  93. package/typings/generated/nrfutil/device/erase.d.ts.map +1 -1
  94. package/typings/generated/nrfutil/device/firmwareRead.d.ts +2 -2
  95. package/typings/generated/nrfutil/device/firmwareRead.d.ts.map +1 -1
  96. package/typings/generated/nrfutil/device/getCoreInfo.d.ts +2 -2
  97. package/typings/generated/nrfutil/device/getCoreInfo.d.ts.map +1 -1
  98. package/typings/generated/nrfutil/device/getFwInfo.d.ts +2 -2
  99. package/typings/generated/nrfutil/device/getFwInfo.d.ts.map +1 -1
  100. package/typings/generated/nrfutil/device/getProtectionStatus.d.ts +2 -2
  101. package/typings/generated/nrfutil/device/getProtectionStatus.d.ts.map +1 -1
  102. package/typings/generated/nrfutil/device/list.d.ts +3 -3
  103. package/typings/generated/nrfutil/device/list.d.ts.map +1 -1
  104. package/typings/generated/nrfutil/device/program.d.ts +2 -2
  105. package/typings/generated/nrfutil/device/program.d.ts.map +1 -1
  106. package/typings/generated/nrfutil/device/recover.d.ts +2 -2
  107. package/typings/generated/nrfutil/device/recover.d.ts.map +1 -1
  108. package/typings/generated/nrfutil/device/reset.d.ts +2 -2
  109. package/typings/generated/nrfutil/device/reset.d.ts.map +1 -1
  110. package/typings/generated/nrfutil/device/setMcuState.d.ts +2 -2
  111. package/typings/generated/nrfutil/device/setMcuState.d.ts.map +1 -1
  112. package/typings/generated/nrfutil/device/setProtectionStatus.d.ts +2 -2
  113. package/typings/generated/nrfutil/device/setProtectionStatus.d.ts.map +1 -1
  114. package/typings/generated/nrfutil/index.d.ts +2 -1
  115. package/typings/generated/nrfutil/index.d.ts.map +1 -1
  116. package/typings/generated/nrfutil/moduleVersion.d.ts +4 -0
  117. package/typings/generated/nrfutil/moduleVersion.d.ts.map +1 -1
  118. package/typings/generated/nrfutil/sandbox.d.ts +2 -2
  119. package/typings/generated/nrfutil/sandbox.d.ts.map +1 -1
  120. package/typings/generated/nrfutil/sandboxTypes.d.ts +10 -1
  121. package/typings/generated/nrfutil/sandboxTypes.d.ts.map +1 -1
  122. package/typings/generated/src/About/ApplicationCard.d.ts.map +1 -1
  123. package/typings/generated/src/About/DeviceCard.d.ts.map +1 -1
  124. package/typings/generated/src/App/App.d.ts +0 -1
  125. package/typings/generated/src/App/App.d.ts.map +1 -1
  126. package/typings/generated/src/Device/DeviceSelector/BasicDeviceInfo.d.ts.map +1 -1
  127. package/typings/generated/src/Device/DeviceSelector/DeviceList/Device.d.ts +0 -1
  128. package/typings/generated/src/Device/DeviceSelector/DeviceList/Device.d.ts.map +1 -1
  129. package/typings/generated/src/Device/DeviceSelector/DeviceList/DeviceList.d.ts.map +1 -1
  130. package/typings/generated/src/Device/DeviceSelector/DeviceList/EditDeviceButtons.d.ts.map +1 -1
  131. package/typings/generated/src/Device/DeviceSelector/DeviceList/MoreDeviceInfo.d.ts +0 -1
  132. package/typings/generated/src/Device/DeviceSelector/DeviceList/MoreDeviceInfo.d.ts.map +1 -1
  133. package/typings/generated/src/Device/DeviceSelector/DeviceSelector.d.ts.map +1 -1
  134. package/typings/generated/src/Device/DeviceSelector/Favorite.d.ts +0 -1
  135. package/typings/generated/src/Device/DeviceSelector/Favorite.d.ts.map +1 -1
  136. package/typings/generated/src/Device/deviceLister.d.ts +1 -15
  137. package/typings/generated/src/Device/deviceLister.d.ts.map +1 -1
  138. package/typings/generated/src/Device/deviceSetup.d.ts +7 -6
  139. package/typings/generated/src/Device/deviceSetup.d.ts.map +1 -1
  140. package/typings/generated/src/Device/deviceSlice.d.ts +16 -15
  141. package/typings/generated/src/Device/deviceSlice.d.ts.map +1 -1
  142. package/typings/generated/src/Device/jprogOperations.d.ts.map +1 -1
  143. package/typings/generated/src/Device/sdfuOperations.d.ts.map +1 -1
  144. package/typings/generated/src/ErrorBoundary/ErrorBoundary.d.ts.map +1 -1
  145. package/typings/generated/src/Feedback/sendFeedback.d.ts.map +1 -1
  146. package/typings/generated/src/InlineInput/NumberInlineInput.d.ts +1 -1
  147. package/typings/generated/src/InlineInput/NumberInlineInput.d.ts.map +1 -1
  148. package/typings/generated/src/InlineInput/NumberInputWithDropdown.d.ts.map +1 -1
  149. package/typings/generated/src/index.d.ts +3 -1
  150. package/typings/generated/src/index.d.ts.map +1 -1
  151. package/typings/generated/src/logging/sendInitialLogMessages.d.ts.map +1 -1
  152. package/typings/generated/src/utils/appDetails.d.ts +4 -0
  153. package/typings/generated/src/utils/appDetails.d.ts.map +1 -0
  154. package/typings/generated/src/utils/appDirs.d.ts +1 -1
  155. package/typings/generated/src/utils/appDirs.d.ts.map +1 -1
  156. package/typings/generated/src/utils/launcherConfig.d.ts +4 -0
  157. package/typings/generated/src/utils/launcherConfig.d.ts.map +1 -0
  158. package/typings/generated/src/utils/packageJson.d.ts +30 -7
  159. package/typings/generated/src/utils/packageJson.d.ts.map +1 -1
  160. package/typings/generated/src/utils/persistentStore.d.ts +3 -2
  161. package/typings/generated/src/utils/persistentStore.d.ts.map +1 -1
  162. package/typings/generated/src/utils/systemReport.d.ts +1 -1
  163. package/typings/generated/src/utils/systemReport.d.ts.map +1 -1
  164. package/typings/generated/src/utils/usageData.d.ts +8 -65
  165. package/typings/generated/src/utils/usageData.d.ts.map +1 -1
  166. package/typings/generated/src/utils/usageDataCommon.d.ts +27 -0
  167. package/typings/generated/src/utils/usageDataCommon.d.ts.map +1 -0
  168. package/typings/generated/src/utils/usageDataMain.d.ts +10 -0
  169. package/typings/generated/src/utils/usageDataMain.d.ts.map +1 -0
  170. package/typings/generated/src/utils/usageDataRenderer.d.ts +10 -0
  171. package/typings/generated/src/utils/usageDataRenderer.d.ts.map +1 -0
  172. package/src/Device/DeviceSelector/DeviceList/device.scss +0 -28
  173. package/src/Device/DeviceSelector/DeviceList/more-device-info.scss +0 -33
  174. package/src/Device/DeviceSelector/favorite.scss +0 -17
@@ -4,10 +4,14 @@
4
4
  * SPDX-License-Identifier: LicenseRef-Nordic-4-Clause
5
5
  */
6
6
 
7
- import React, { useCallback, useEffect, useState } from 'react';
7
+ import React, { useCallback, useEffect, useRef, useState } from 'react';
8
8
  import { useDispatch, useSelector } from 'react-redux';
9
9
 
10
+ import { NrfutilDeviceLib } from '../../../nrfutil';
10
11
  import { DeviceTraits } from '../../../nrfutil/device/common';
12
+ import logger from '../../logging';
13
+ import usageData from '../../utils/usageData';
14
+ import { simplifyDeviceForLogging } from '../../utils/usageDataCommon';
11
15
  import useHotKey from '../../utils/useHotKey';
12
16
  import {
13
17
  clearWaitForDevice,
@@ -21,8 +25,10 @@ import {
21
25
  deselectDevice,
22
26
  Device,
23
27
  deviceIsSelected as deviceIsSelectedSelector,
28
+ isDeviceWithSerialNumber,
24
29
  selectDevice,
25
- selectedSerialNumber,
30
+ selectedDevice,
31
+ setSelectedDeviceInfo,
26
32
  } from '../deviceSlice';
27
33
  import DeviceList from './DeviceList/DeviceList';
28
34
  import SelectDevice from './SelectDevice';
@@ -54,36 +60,73 @@ export default ({
54
60
  const [deviceListVisible, setDeviceListVisible] = useState(false);
55
61
 
56
62
  const deviceIsSelected = useSelector(deviceIsSelectedSelector);
57
- const selectedSN = useSelector(selectedSerialNumber);
63
+ const currentDevice = useSelector(selectedDevice);
58
64
  const waitingToAutoReconnect = useSelector(getWaitingToAutoReselect);
59
65
  const showSelectedDevice = deviceIsSelected || waitingToAutoReconnect;
60
66
 
61
- const doDeselectDevice = useCallback(() => {
62
- dispatch(clearWaitForDevice());
63
- dispatch(setAutoSelectDevice(undefined));
64
- onDeviceDeselected();
65
- dispatch(deselectDevice());
66
- }, [dispatch, onDeviceDeselected]);
67
+ const doDeselectDevice = useCallback(
68
+ (device?: Device) => {
69
+ if (device) {
70
+ usageData.sendUsageData(
71
+ 'device deselected ',
72
+ simplifyDeviceForLogging(device)
73
+ );
74
+ }
75
+
76
+ dispatch(clearWaitForDevice());
77
+ dispatch(setAutoSelectDevice(undefined));
78
+ onDeviceDeselected();
79
+ dispatch(deselectDevice());
80
+ },
81
+ [dispatch, onDeviceDeselected]
82
+ );
83
+
84
+ const abortController = useRef<AbortController>();
67
85
 
68
86
  // Ensure that useCallback is
69
87
  // not updated frequently as this
70
88
  // will have a side effect to stop and start the hotplug events
71
89
  const doSelectDevice = useCallback(
72
- (device: Device, autoReselected: boolean) => {
90
+ async (device: Device, autoReselected: boolean) => {
73
91
  dispatch(clearWaitForDevice());
74
92
  setDeviceListVisible(false);
75
93
  dispatch(selectDevice(device));
76
94
  dispatch(setAutoSelectDevice(device));
77
95
  onDeviceSelected(device, autoReselected);
96
+
97
+ abortController.current?.abort();
98
+ abortController.current = new AbortController();
99
+ const deviceInfo = await NrfutilDeviceLib.deviceInfo(
100
+ device,
101
+ undefined,
102
+ undefined,
103
+ abortController.current
104
+ );
105
+ abortController.current = undefined;
106
+ setSelectedDeviceInfo(deviceInfo);
107
+
108
+ usageData.sendUsageData('device selected', {
109
+ device: simplifyDeviceForLogging(device),
110
+ deviceInfo,
111
+ });
112
+
78
113
  if (deviceSetupConfig) {
79
- dispatch(
80
- setupDevice(
81
- device,
82
- deviceSetupConfig,
83
- onDeviceIsReady,
84
- doDeselectDevice
85
- )
86
- );
114
+ if (isDeviceWithSerialNumber(device)) {
115
+ dispatch(
116
+ setupDevice(
117
+ device,
118
+ deviceSetupConfig,
119
+ onDeviceIsReady,
120
+ doDeselectDevice,
121
+ deviceInfo
122
+ )
123
+ );
124
+ } else {
125
+ logger.warn(
126
+ `Selected device has no serial number. Device setup is not supported`
127
+ );
128
+ onDeviceIsReady(device);
129
+ }
87
130
  }
88
131
  },
89
132
  [
@@ -133,7 +176,7 @@ export default ({
133
176
  <div className="core19-device-selector">
134
177
  {showSelectedDevice ? (
135
178
  <SelectedDevice
136
- doDeselectDevice={doDeselectDevice}
179
+ doDeselectDevice={() => doDeselectDevice(currentDevice)}
137
180
  toggleDeviceListVisible={toggleDeviceListVisible}
138
181
  />
139
182
  ) : (
@@ -145,13 +188,13 @@ export default ({
145
188
  <DeviceList
146
189
  isVisible={deviceListVisible}
147
190
  doSelectDevice={(device, autoReselected) => {
148
- if (device.serialNumber === selectedSN) {
191
+ if (device.id === currentDevice?.id) {
149
192
  setDeviceListVisible(false);
150
193
  return;
151
194
  }
152
195
 
153
196
  if (deviceIsSelected) {
154
- doDeselectDevice();
197
+ doDeselectDevice(currentDevice);
155
198
  }
156
199
 
157
200
  doSelectDevice(device, autoReselected);
@@ -8,19 +8,18 @@ import React, { FC } from 'react';
8
8
  import { useDispatch } from 'react-redux';
9
9
 
10
10
  import PseudoButton from '../../PseudoButton/PseudoButton';
11
+ import classNames from '../../utils/classNames';
11
12
  import { Device, toggleDeviceFavorited } from '../deviceSlice';
12
13
 
13
- import './favorite.scss';
14
-
15
14
  export const MakeDeviceFavorite: FC<{ device: Device }> = ({ device }) => {
16
15
  const dispatch = useDispatch();
17
16
 
18
17
  const toggleFavorite = () => {
19
- dispatch(toggleDeviceFavorited(device.serialNumber));
18
+ dispatch(toggleDeviceFavorited(device));
20
19
  };
21
20
 
22
21
  return (
23
- <PseudoButton className="make-favorite" onClick={toggleFavorite}>
22
+ <PseudoButton className="tw-mr-[1ex]" onClick={toggleFavorite}>
24
23
  <span
25
24
  className={`mdi star ${
26
25
  device.favorite ? 'mdi-star-off' : 'mdi-star'
@@ -35,15 +34,16 @@ export const FavoriteIndicator: FC<{ device: Device }> = ({ device }) => {
35
34
  const dispatch = useDispatch();
36
35
 
37
36
  const toggleFavorite = () => {
38
- dispatch(toggleDeviceFavorited(device.serialNumber));
37
+ dispatch(toggleDeviceFavorited(device));
39
38
  };
40
39
 
41
- return (
40
+ return device.serialNumber ? (
42
41
  <PseudoButton
43
- className={`mdi ${
44
- device.favorite ? 'mdi-star' : 'mdi-star-outline'
45
- }`}
42
+ className={classNames(
43
+ !device.favorite && 'tw-invisible group-hover:tw-visible',
44
+ `mdi ${device.favorite ? 'mdi-star' : 'mdi-star-outline'}`
45
+ )}
46
46
  onClick={toggleFavorite}
47
47
  />
48
- );
48
+ ) : null;
49
49
  };
@@ -16,9 +16,6 @@
16
16
  .details {
17
17
  width: inherit;
18
18
 
19
- display: flex;
20
- flex-direction: column;
21
-
22
19
  line-height: 1;
23
20
 
24
21
  .name {
@@ -49,14 +46,5 @@
49
46
  text-overflow: ellipsis;
50
47
  }
51
48
  }
52
-
53
- .toggles {
54
- display: flex;
55
- flex-direction: column;
56
- align-items: center;
57
-
58
- width: 44px;
59
- margin-right: 10px;
60
- }
61
49
  }
62
50
  }
@@ -199,7 +199,7 @@ const devicesByPca: { [P in KnownDevicePCA]: DeviceInfo } = {
199
199
 
200
200
  const deviceByPca = (device: Device) =>
201
201
  devicesByPca[
202
- String(device.jlink?.boardVersion).toUpperCase() as KnownDevicePCA
202
+ String(device.devkit?.boardVersion).toUpperCase() as KnownDevicePCA
203
203
  ];
204
204
 
205
205
  const NORDIC_VENDOR_ID = '1915';
@@ -252,7 +252,7 @@ export const displayedDeviceName = (
252
252
  return device.nickname;
253
253
  }
254
254
 
255
- return deviceInfo(device).name || device.jlink?.boardVersion || 'Unknown';
255
+ return deviceInfo(device).name || device.devkit?.boardVersion || 'Unknown';
256
256
  };
257
257
 
258
258
  export const productPageUrl = (device: Device) =>
@@ -4,14 +4,12 @@
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';
11
+ import usageData from '../utils/usageData';
12
+ import { simplifyDeviceForLogging } from '../utils/usageDataCommon';
15
13
  import {
16
14
  clearWaitForDevice,
17
15
  clearWaitForDeviceTimeout,
@@ -23,7 +21,13 @@ import {
23
21
  WaitForDevice,
24
22
  } from './deviceAutoSelectSlice';
25
23
  import { closeDeviceSetupDialog } from './deviceSetupSlice';
26
- import { addDevice, Device, removeDevice } from './deviceSlice';
24
+ import {
25
+ addDevice,
26
+ Device,
27
+ removeDevice,
28
+ selectDevice,
29
+ setSelectedDeviceInfo,
30
+ } from './deviceSlice';
27
31
  import { isDeviceInDFUBootloader } from './sdfuOperations';
28
32
 
29
33
  let stopNrfutilDevice: (callback?: () => void) => void;
@@ -52,6 +56,11 @@ const shouldAutoReselect = (
52
56
  // device is still connected
53
57
  if (disconnectionTime === undefined) return false;
54
58
 
59
+ // device does not have sn
60
+ if (!addedDevice.serialNumber) {
61
+ return false;
62
+ }
63
+
55
64
  // The device that was selected when disconnection occurred is not yet connected
56
65
  if (addedDevice.serialNumber !== autoReselectDevice.serialNumber) {
57
66
  return false;
@@ -100,28 +109,6 @@ const initAutoReconnectTimeout =
100
109
  );
101
110
  };
102
111
 
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
112
  export const hasValidDeviceTraits = (
126
113
  deviceTraits: DeviceTraits,
127
114
  requiredTraits: DeviceTraits
@@ -144,7 +131,7 @@ const removeDeviceFromList =
144
131
  (dispatch, getState) => {
145
132
  if (
146
133
  removedDevice.serialNumber !==
147
- getState().device.selectedSerialNumber
134
+ getState().device.selectedDevice?.serialNumber
148
135
  ) {
149
136
  dispatch(removeDevice(removedDevice));
150
137
  onDeviceDisconnected(removedDevice);
@@ -176,22 +163,27 @@ export const startWatchingDevices =
176
163
  doSelectDevice: (device: Device, autoReselected: boolean) => void
177
164
  ): AppThunk<RootState, void> =>
178
165
  (dispatch, getState) => {
179
- const onDeviceArrived = (device: NrfutilDeviceWithSerialnumber) => {
166
+ const onDeviceArrived = async (device: NrfutilDevice) => {
180
167
  if (hasValidDeviceTraits(device.traits, deviceListing)) {
181
- device = wrapDeviceFromNrfdl(device);
168
+ usageData.sendUsageData(
169
+ 'device connected',
170
+ simplifyDeviceForLogging(device)
171
+ );
182
172
  if (
183
- device.serialNumber &&
184
- !getState().device.devices.has(device.serialNumber)
173
+ !getState().device.devices.find(
174
+ d =>
175
+ d.id === device.id ||
176
+ (device.serialNumber && // we want to disregard comparing devices with no sn
177
+ d.serialNumber === device.serialNumber)
178
+ )
185
179
  ) {
186
180
  onDeviceConnected(device);
187
181
  }
188
182
 
189
- const sn = getState().device.selectedSerialNumber;
190
183
  const disconnectionTime =
191
184
  getState().deviceAutoSelect.disconnectionTime;
192
185
  const autoSelectDevice = getState().deviceAutoSelect.device;
193
- const selectedDevice =
194
- sn !== null ? getState().device.devices.get(sn) : undefined;
186
+ const selectedDevice = getState().device.selectedDevice;
195
187
 
196
188
  const result = shouldAutoReselect(
197
189
  device,
@@ -202,17 +194,32 @@ export const startWatchingDevices =
202
194
  );
203
195
 
204
196
  dispatch(addDevice(device));
205
- const deviceWithPersistedData = getState().device.devices.get(
206
- device.serialNumber
197
+ const deviceWithPersistedData = getState().device.devices.find(
198
+ d => d.serialNumber === device.serialNumber
207
199
  );
208
200
 
209
201
  if (!deviceWithPersistedData) return;
210
202
 
211
- if (result) {
203
+ // We might get multiple events with the same info so no to trigger auto reconnect multiple times we
204
+ // only do it once per device id
205
+ if (
206
+ result &&
207
+ getState().deviceAutoSelect.lastArrivedDeviceId !==
208
+ deviceWithPersistedData.id
209
+ ) {
210
+ dispatch(
211
+ setLastArrivedDeviceId(deviceWithPersistedData.id)
212
+ );
213
+
214
+ const deviceInfo = await NrfutilDeviceLib.deviceInfo(
215
+ device
216
+ );
217
+
212
218
  logger.info(
213
219
  `Auto Reconnecting Device SN: ${deviceWithPersistedData.serialNumber}`
214
220
  );
215
221
  doSelectDevice(deviceWithPersistedData, true);
222
+ dispatch(setSelectedDeviceInfo(deviceInfo));
216
223
  } else if (
217
224
  deviceWithPersistedData.serialNumber ===
218
225
  getState().deviceAutoSelect.device?.serialNumber
@@ -220,6 +227,10 @@ export const startWatchingDevices =
220
227
  const waitForDevice =
221
228
  getState().deviceAutoSelect.waitForDevice;
222
229
 
230
+ const deviceInfo = await NrfutilDeviceLib.deviceInfo(
231
+ device
232
+ );
233
+
223
234
  // Device lib might fail to advertise that a device has left before it rejoins (Mainly OSx)
224
235
  // but we still need to trigger the onSuccess if a device 'reappeared' with a different 'id'
225
236
  // and there is an outstanding waitForDevice Request. In this case the disconnectionTime was
@@ -245,8 +256,7 @@ export const startWatchingDevices =
245
256
  deviceWithPersistedData
246
257
  )) ||
247
258
  (waitForDevice.when === 'applicationMode' &&
248
- deviceWithPersistedData.dfuTriggerInfo !==
249
- null) ||
259
+ deviceInfo?.dfuTriggerVersion) ||
250
260
  (selectedDevice &&
251
261
  waitForDevice.when === 'sameTraits' &&
252
262
  hasSameDeviceTraits(
@@ -269,6 +279,9 @@ export const startWatchingDevices =
269
279
  clearWaitForDeviceTimeout(waitForDevice.once)
270
280
  );
271
281
 
282
+ dispatch(selectDevice(deviceWithPersistedData));
283
+ dispatch(setSelectedDeviceInfo(deviceInfo));
284
+
272
285
  if (waitForDevice.onSuccess)
273
286
  waitForDevice.onSuccess(
274
287
  deviceWithPersistedData
@@ -288,8 +301,9 @@ export const startWatchingDevices =
288
301
  const waitForDevice =
289
302
  getState().deviceAutoSelect.waitForDevice;
290
303
  if (
304
+ device.serialNumber && // we want to disregard comparing devices with no sn
291
305
  device.serialNumber ===
292
- getState().deviceAutoSelect.device?.serialNumber
306
+ getState().deviceAutoSelect.device?.serialNumber
293
307
  ) {
294
308
  if (waitForDevice) {
295
309
  dispatch(setArrivedButWrongWhen(undefined));
@@ -334,7 +348,10 @@ export const startWatchingDevices =
334
348
  stopWatchingDevices(async () => {
335
349
  const operation = await NrfutilDeviceLib.list(
336
350
  deviceListing,
337
- d => d.forEach(onDeviceArrived),
351
+ d => {
352
+ d.forEach(onDeviceArrived);
353
+ dispatch(autoSelectDeviceCLI(doSelectDevice));
354
+ },
338
355
  error => {
339
356
  logger.error(error);
340
357
  },
@@ -346,28 +363,63 @@ export const startWatchingDevices =
346
363
  callback?.();
347
364
  });
348
365
  };
349
-
350
- if (!autoSelectDeviceCLISerialUsed) {
351
- const autoSelectSN = getAutoSelectDeviceCLISerial();
352
-
353
- if (autoSelectSN !== undefined) {
354
- const autoSelectDevice =
355
- getState().device.devices.get(autoSelectSN);
356
-
357
- if (autoSelectDevice)
358
- doSelectDevice(autoSelectDevice, true);
359
- }
360
- autoSelectDeviceCLISerialUsed = true;
361
- }
362
366
  });
363
367
  };
364
368
 
365
- const getAutoSelectDeviceCLISerial = () => {
369
+ const getAutoSelectDeviceCLIProperty = (
370
+ property: string,
371
+ findDevice: (value: string) => Device | undefined
372
+ ) => {
366
373
  const { argv } = process;
367
- const serialIndex = argv.findIndex(arg => arg === '--deviceSerial');
368
- return serialIndex > -1 ? argv[serialIndex + 1] : undefined;
374
+ const index = argv.findIndex(arg => arg === property);
375
+ return index > -1
376
+ ? { index, device: findDevice(argv[index + 1]) }
377
+ : undefined;
369
378
  };
370
379
 
380
+ const getAutoSelectDevice = (devices: Device[]) => {
381
+ const serialNumber = getAutoSelectDeviceCLIProperty('--deviceSerial', sn =>
382
+ devices.find(device => device.serialNumber === sn)
383
+ );
384
+ const serialPort = getAutoSelectDeviceCLIProperty('--comPort', portPath =>
385
+ devices.find(device =>
386
+ device.serialPorts?.find(port => port.comName === portPath)
387
+ )
388
+ );
389
+
390
+ if (serialNumber && serialPort) {
391
+ if (serialNumber.index > serialPort.index) {
392
+ return serialPort.device;
393
+ }
394
+
395
+ return serialNumber.device;
396
+ }
397
+
398
+ if (serialNumber) {
399
+ return serialNumber.device;
400
+ }
401
+
402
+ if (serialPort) {
403
+ return serialPort.device;
404
+ }
405
+ };
406
+
407
+ const autoSelectDeviceCLI =
408
+ (
409
+ doSelectDevice: (device: Device, autoReselected: boolean) => void
410
+ ): AppThunk<RootState> =>
411
+ (_, getState) => {
412
+ if (!autoSelectDeviceCLISerialUsed) {
413
+ const autoSelectDevice = getAutoSelectDevice(
414
+ getState().device.devices
415
+ );
416
+
417
+ if (autoSelectDevice) doSelectDevice(autoSelectDevice, true);
418
+
419
+ autoSelectDeviceCLISerialUsed = true;
420
+ }
421
+ };
422
+
371
423
  export const stopWatchingDevices = (callback?: () => void) => {
372
424
  if (stopNrfutilDevice) stopNrfutilDevice(callback);
373
425
  else callback?.();
@@ -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';
@@ -12,7 +13,7 @@ import {
12
13
  setDeviceSetupProgress,
13
14
  setDeviceSetupProgressMessage,
14
15
  } from './deviceSetupSlice';
15
- import { Device } from './deviceSlice';
16
+ import { Device, DeviceWithSerialNumber } from './deviceSlice';
16
17
  import { InitPacket } from './initPacket';
17
18
 
18
19
  export interface DfuEntry {
@@ -33,15 +34,24 @@ export interface JprogEntry {
33
34
  }
34
35
 
35
36
  export interface DeviceSetup {
36
- supportsProgrammingMode: (device: Device) => boolean; // Return true if this device can be programed using this interface e.g. MCU Boot or DFU
37
- getFirmwareOptions: (device: Device) => {
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: (device: Device) => AppThunk<
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 => deviceSetup.supportsProgrammingMode(device)
90
+ deviceSetup =>
91
+ deviceSetup.supportsProgrammingMode(device, deviceInfo)
79
92
  );
80
93
 
81
94
  const possibleFirmware = validDeviceSetups
82
- .map(deviceSetup => deviceSetup.getFirmwareOptions(device))
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.jlink?.deviceFamily || 'Unknown'} `
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) {
@@ -224,10 +239,11 @@ export const prepareDevice =
224
239
 
225
240
  export const setupDevice =
226
241
  (
227
- device: Device,
242
+ device: DeviceWithSerialNumber,
228
243
  deviceSetupConfig: DeviceSetupConfig,
229
244
  onDeviceIsReady: (device: Device) => void,
230
- doDeselectDevice: () => void
245
+ doDeselectDevice: (device?: Device) => 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.selectedSerialNumber ===
261
+ getState().device.selectedDevice?.serialNumber ===
246
262
  d.serialNumber
247
263
  ) {
248
264
  onDeviceIsReady(d);
@@ -254,7 +270,8 @@ export const setupDevice =
254
270
  `Error while setting up device ${device.serialNumber}`
255
271
  );
256
272
  logger.error(describeError(error));
257
- doDeselectDevice();
258
- }
273
+ doDeselectDevice(getState().device.selectedDevice);
274
+ },
275
+ deviceInfo
259
276
  )
260
277
  );