@@ -27,18 +27,15 @@ module.exports = class eSimCommands extends CLICommandBase {
27
27
async provision ( args ) {
28
28
this . _validateArgs ( args ) ;
29
29
30
+ // Get the serial port and device details
30
31
const port = await this . _getSerialPortForSingleDevice ( ) ;
31
-
32
- // get the device usb handle from the serial port
33
32
const device = await this . serial . whatSerialPortDidYouMean ( port ) ;
34
33
const platform = platformForId ( device . specs . productId ) . name ;
35
34
36
35
console . log ( `${ os . EOL } Provisioning device ${ device . deviceId } with platform ${ platform } ` ) ;
37
36
37
+ // Flash firmware and retrieve EID
38
38
await this . _flashATPassThroughFirmware ( device , platform , port ) ;
39
-
40
- // This assumes that the input JSON does not have a mapping between EID and profiles
41
- // So obtain the EID from the device and put it in outupt JSON
42
39
const eid = await this . _getEid ( port ) ;
43
40
console . log ( `${ os . EOL } EID: ${ eid } ` ) ;
44
41
@@ -49,59 +46,55 @@ module.exports = class eSimCommands extends CLICommandBase {
49
46
const inputJsonData = JSON . parse ( input ) ;
50
47
51
48
// Get the profile list that matches the EID that is given by the field eid
52
- const eidBlock = inputJsonData . EIDs . filter ( ( block ) => block . eid === eid ) ;
53
- const profiles = eidBlock [ 0 ] ?. profiles ;
54
- if ( profiles . length === 0 ) {
55
- throw new Error ( 'No profiles to provision in the input json ' ) ;
49
+ const eidBlock = inputJsonData . EIDs . find ( ( block ) => block . esim_id === eid ) ;
50
+
51
+ if ( ! eidBlock || ! eidBlock . profiles || eidBlock . profiles . length === 0 ) {
52
+ throw new Error ( 'No profiles to provision in the input JSON ' ) ;
56
53
}
57
54
55
+ const profiles = eidBlock ?. profiles ;
56
+
58
57
console . log ( `${ os . EOL } Provisioning the following profiles: ` ) ;
59
- let cnt = 0 ;
60
- for ( const profile of profiles ) {
61
- cnt ++ ;
62
- const smdp = profile . smdp ;
63
- const matchingId = profile . matching_id ;
64
- const rspUrl = `1\$${ smdp } \$${ matchingId } ` ;
65
- console . log ( `\t${ cnt } . ${ profile . provider } (${ rspUrl } )` ) ;
66
- }
58
+ profiles . forEach ( ( profile , index ) => {
59
+ const rspUrl = `1\$${ profile . smdp } \$${ profile . matching_id } ` ;
60
+ console . log ( `\t${ index + 1 } . ${ profile . provider } (${ rspUrl } )` ) ;
61
+ } ) ;
67
62
68
63
// Download each profile
69
- cnt = 0 ;
70
- for ( const profile of profiles ) {
71
- cnt ++ ;
72
- let iccid = null ;
73
- const smdp = profile . smdp ;
74
- const matchingId = profile . matching_id ;
75
- const rspUrl = `1\$${ smdp } \$${ matchingId } ` ;
76
- console . log ( `${ os . EOL } ${ cnt } . Downloading ${ profile . provider } profile from ${ rspUrl } ` ) ;
64
+ for ( const [ index , profile ] of profiles . entries ( ) ) {
65
+ const rspUrl = `1\$${ profile . smdp } \$${ profile . matching_id } ` ;
66
+ console . log ( `${ os . EOL } ${ index + 1 } . Downloading ${ profile . provider } profile from ${ rspUrl } ` ) ;
77
67
78
68
const start = Date . now ( ) ;
79
-
80
- const res = await execa ( this . lpa , [ 'download' , rspUrl , `--serial=${ port } ` ] ) ;
81
-
82
- const end = Date . now ( ) ;
83
- const timeTaken = ( end - start ) / 1000 ;
84
-
85
- const output = res . stdout ;
86
- if ( output . includes ( 'Profile successfully downloaded' ) ) {
87
- console . log ( `${ os . EOL } \tProfile successfully downloaded in ${ timeTaken } sec` ) ;
88
- const iccidLine = output . split ( '\n' ) . find ( ( line ) => line . includes ( 'Profile with ICCID' ) ) ;
89
- // FIXME: Get the string after the "ICCID" string
90
- iccid = iccidLine . split ( ' ' ) [ 4 ] ;
91
- } else {
92
- console . log ( `${ os . EOL } \tProfile download failed` ) ;
69
+ let iccid = null ;
70
+
71
+ try {
72
+ const res = await execa ( this . lpa , [ 'download' , rspUrl , `--serial=${ port } ` ] ) ;
73
+ const timeTaken = ( ( Date . now ( ) - start ) / 1000 ) . toFixed ( 2 ) ;
74
+
75
+ const output = res . stdout ;
76
+ if ( output . includes ( 'Profile successfully downloaded' ) ) {
77
+ console . log ( `${ os . EOL } \tProfile successfully downloaded in ${ timeTaken } sec` ) ;
78
+ const iccidLine = output . split ( '\n' ) . find ( ( line ) => line . includes ( 'Profile with ICCID' ) ) ;
79
+ if ( iccidLine ) {
80
+ iccid = iccidLine . split ( ' ' ) [ 4 ] ; // Extract ICCID
81
+ }
82
+ } else {
83
+ console . log ( `${ os . EOL } \tProfile download failed` ) ;
84
+ }
85
+
86
+ const outputData = {
87
+ EID : eid ,
88
+ provider : profile . provider ,
89
+ iccid,
90
+ time : timeTaken ,
91
+ output,
92
+ } ;
93
+
94
+ this . _addToJson ( this . outputJson , outputData ) ;
95
+ } catch ( err ) {
96
+ console . error ( `${ os . EOL } \tFailed to download profile: ${ err . message } ` ) ;
93
97
}
94
-
95
- const outputData = {
96
- EID : eid ,
97
- provider : profile . provider ,
98
- iccid : iccid ,
99
- time : timeTaken ,
100
- output : output
101
- } ;
102
-
103
- await this . _addToJson ( this . outputJson , outputData ) ;
104
- console . log ( os . EOL ) ;
105
98
}
106
99
107
100
console . log ( `${ os . EOL } Provisioning complete` ) ;
@@ -127,79 +120,129 @@ module.exports = class eSimCommands extends CLICommandBase {
127
120
128
121
async _getSerialPortForSingleDevice ( ) {
129
122
const deviceSerialPorts = await usbUtils . getUsbSystemPathsForMac ( ) ;
130
- if ( deviceSerialPorts . length > 1 ) {
131
- throw new Error ( 'Multiple devices found. Please unplug all but one device or use --bulk option' ) ;
132
- }
123
+ if ( deviceSerialPorts . length !== 1 ) {
124
+ const errorMessage = deviceSerialPorts . length > 1
125
+ ? 'Multiple devices found. Please unplug all but one device or use the --bulk option.'
126
+ : 'No devices found. Please connect a device and try again.' ;
127
+ throw new Error ( errorMessage ) ;
128
+ }
133
129
return deviceSerialPorts [ 0 ] ;
134
130
}
135
131
136
132
async _flashATPassThroughFirmware ( device , platform , port ) {
137
- // Obtain the pre-compiled firmware binary from local folder
138
- // TODO: Do this with binary inspect for more reliability
133
+ // Locate the firmware binary
134
+ console . log ( ` ${ os . EOL } Locating firmware for platform: ${ platform } ` ) ;
139
135
const fwBinaries = fs . readdirSync ( PATH_TO_PASS_THROUGH_BINARIES ) ;
140
- const validBin = fwBinaries . filter ( ( file ) => file . endsWith ( `${ platform } .bin` ) ) ;
141
- const fwPath = path . join ( PATH_TO_PASS_THROUGH_BINARIES , validBin [ 0 ] ) ;
136
+ const validBin = fwBinaries . find ( ( file ) => file . endsWith ( `${ platform } .bin` ) ) ;
137
+
138
+ if ( ! validBin ) {
139
+ throw new Error ( `No firmware binary found for platform: ${ platform } ` ) ;
140
+ }
141
+
142
+ const fwPath = path . join ( PATH_TO_PASS_THROUGH_BINARIES , validBin ) ;
143
+ console . log ( `${ os . EOL } Found firmware: ${ fwPath } ` ) ;
142
144
143
- // Flash the AT passthrough firmware
144
- console . log ( `${ os . EOL } Flashing AT passthrough firmware ${ fwPath } to the device` ) ;
145
+ // Flash the firmware
146
+ console . log ( `${ os . EOL } Flashing AT passthrough firmware to the device... ` ) ;
145
147
const flashCmdInstance = new FlashCommand ( ) ;
146
- await flashCmdInstance . flashLocal ( { files : [ fwPath ] , applicationOnly : true , verbose : true } ) ;
147
- console . log ( `${ os . EOL } AT passthrough firmware flashed` ) ;
148
+ await flashCmdInstance . flashLocal ( {
149
+ files : [ fwPath ] ,
150
+ applicationOnly : true ,
151
+ verbose : true ,
152
+ } ) ;
153
+ console . log ( `${ os . EOL } Firmware flashed successfully` ) ;
148
154
155
+ // Wait for the device to respond
156
+ console . log ( `${ os . EOL } Waiting for device to respond...` ) ;
149
157
const deviceResponded = await usbUtils . waitForDeviceToRespond ( device . deviceId ) ;
158
+
150
159
if ( ! deviceResponded ) {
151
- throw new Error ( 'Device did not respond after flashing AT passthrough firmware' ) ;
160
+ throw new Error ( 'Device did not respond after flashing firmware' ) ;
152
161
}
153
- console . log ( `${ os . EOL } Device responded after flashing AT passthrough firmware ` ) ;
162
+ console . log ( `${ os . EOL } Device responded successfully ` ) ;
154
163
await deviceResponded . close ( ) ;
155
164
156
- // FIXME: Use the firmware that does not have initial logs and then remove this block
157
- console . log ( `${ os . EOL } Wait for the initial logs to clear up ` ) ;
165
+ // Handle initial logs (temporary workaround)
166
+ console . log ( `${ os . EOL } Clearing initial logs (temporary workaround)... ` ) ;
158
167
console . log ( `${ os . EOL } --------------------------------------` ) ;
159
168
const monitor = await this . serial . monitorPort ( { port, follow : false } ) ;
160
- await utilities . delay ( 30000 ) ;
169
+
170
+ // Wait for logs to clear
171
+ await utilities . delay ( 30000 ) ; // 30-second delay
161
172
await monitor . stop ( ) ;
162
- await utilities . delay ( 5000 ) ;
173
+ await utilities . delay ( 5000 ) ; // Additional delay to ensure logs are cleared
163
174
console . log ( `${ os . EOL } --------------------------------------` ) ;
164
- console . log ( `${ os . EOL } Initial logs likely cleared` ) ;
175
+ console . log ( `${ os . EOL } Initial logs cleared` ) ;
165
176
}
166
177
178
+
167
179
async _getEid ( port ) {
168
- console . log ( `${ os . EOL } Getting EID from the device` ) ;
169
- const resEid = await execa ( this . lpa , [ 'getEid' , `--serial=${ port } ` ] ) ;
170
- const eidOutput = resEid . stdout ;
171
- let eid = null ;
172
-
173
- // get the line in eidOutput that starts with "EID: " and then get the next word
174
- eidOutput . split ( '\n' ) . forEach ( ( line ) => {
175
- if ( line . startsWith ( 'EID: ' ) ) {
176
- eid = line . split ( ' ' ) [ 1 ] ;
180
+ console . log ( `${ os . EOL } Getting EID from the device...` ) ;
181
+
182
+ try {
183
+ const resEid = await execa ( this . lpa , [ 'getEid' , `--serial=${ port } ` ] ) ;
184
+ const eidOutput = resEid . stdout ;
185
+
186
+ // Find the line starting with "EID: " and extract the EID
187
+ const eid = eidOutput
188
+ . split ( '\n' )
189
+ . find ( ( line ) => line . startsWith ( 'EID: ' ) )
190
+ ?. split ( ' ' ) [ 1 ] ;
191
+
192
+ if ( ! eid ) {
193
+ throw new Error ( 'EID not found in the output' ) ;
177
194
}
178
- } ) ;
179
- if ( ! eid ) {
180
- throw new Error ( 'EID not found in the output' ) ;
195
+ return eid ;
196
+ } catch ( error ) {
197
+ console . error ( `${ os . EOL } Failed to retrieve EID: ${ error . message } ` ) ;
198
+ throw error ;
181
199
}
182
- return eid ;
183
200
}
184
201
185
202
async _checkForExistingProfiles ( port ) {
186
- console . log ( `${ os . EOL } Checking for existing profiles` ) ;
187
- const resProfiles = await execa ( this . lpa , [ 'listProfiles' , `--serial=${ port } ` ] ) ;
188
- const profilesOutput = resProfiles . stdout ;
189
- const profilesList = profilesOutput
190
- . split ( '\n' )
191
- . filter ( ( line ) => line . match ( / ^ \d + : \[ \w + , \s (?: e n a b l e d | d i s a b l e d ) , \s ? \] $ / ) ) ;
192
- // console.log('Profiles list: ', profilesList);
193
- if ( profilesList . length > 0 ) {
194
- throw new Error ( 'Profile(s) already exist. Bad device bucket.' ) ;
203
+ console . log ( `${ os . EOL } Checking for existing profiles...` ) ;
204
+
205
+ try {
206
+ const resProfiles = await execa ( this . lpa , [ 'listProfiles' , `--serial=${ port } ` ] ) ;
207
+ const profilesOutput = resProfiles . stdout ;
208
+
209
+ // Extract lines matching the profile format
210
+ const profilesList = profilesOutput
211
+ . split ( '\n' )
212
+ . filter ( ( line ) => line . match ( / ^ \d + : \[ \w + , \s (?: e n a b l e d | d i s a b l e d ) , \s ? \] $ / ) ) ;
213
+
214
+ if ( profilesList . length > 0 ) {
215
+ console . error ( `${ os . EOL } Profile(s) already exist:` , profilesList ) ;
216
+ throw new Error ( 'Profile(s) already exist. Device bucket is not clean.' ) ;
217
+ }
218
+
219
+ console . log ( `${ os . EOL } No existing profiles found` ) ;
220
+ } catch ( error ) {
221
+ console . error ( `${ os . EOL } Failed to check for existing profiles: ${ error . message } ` ) ;
222
+ throw error ;
195
223
}
196
- console . log ( `${ os . EOL } No existing profiles found` ) ;
197
224
}
225
+
226
+ _addToJson ( jsonFile , data ) {
227
+ try {
228
+ // Read and parse existing JSON data
229
+ let existingJson = [ ] ;
230
+ if ( fs . existsSync ( jsonFile ) ) {
231
+ const existing = fs . readFileSync ( jsonFile , 'utf-8' ) ;
232
+ existingJson = JSON . parse ( existing ) ;
233
+ if ( ! Array . isArray ( existingJson ) ) {
234
+ throw new Error ( 'Existing JSON data is not an array' ) ;
235
+ }
236
+ }
198
237
199
- async _addToJson ( jsonFile , data ) {
200
- const existing = fs . readFileSync ( jsonFile ) ;
201
- const existingJson = JSON . parse ( existing ) ;
202
- existingJson . push ( data ) ;
203
- fs . writeFileSync ( jsonFile , JSON . stringify ( existingJson , null , 4 ) ) ;
238
+ existingJson . push ( data ) ;
239
+
240
+ // Write updated JSON back to the file with indentation
241
+ fs . writeFileSync ( jsonFile , JSON . stringify ( existingJson , null , 4 ) ) ;
242
+ console . log ( 'Data appended successfully' ) ;
243
+ } catch ( error ) {
244
+ console . error ( `Failed to append data to JSON file: ${ error . message } ` ) ;
245
+ }
204
246
}
247
+
205
248
} ;
0 commit comments