Skip to content

Commit

Permalink
use serial identify in case the device does not support control request
Browse files Browse the repository at this point in the history
  • Loading branch information
hugomontero committed May 9, 2024
1 parent c2b8b85 commit 685cb56
Showing 1 changed file with 117 additions and 5 deletions.
122 changes: 117 additions & 5 deletions src/cmd/serial.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ const usbUtils = require('./usb-util');
const { platformForId } = require('../lib/platform');
const { FirmwareModuleDisplayNames } = require('particle-usb');

const IDENTIFY_COMMAND_TIMEOUT = 20000;


// TODO: DRY this up somehow
// The categories of output will be handled via the log class, and similar for protip.
Expand Down Expand Up @@ -259,18 +261,38 @@ module.exports = class SerialCommand extends CLICommandBase {
// Obtain system firmware version
fwVer = device.firmwareVersion;


// If the device is a cellular device, obtain imei and iccid
try {
const features = platformForId(device.platformId).features;
if (features.includes('cellular')) {

const features = platformForId(device.platformId).features;
if (features.includes('cellular')) {
let isControlRequestSupported = true;
try {
const cellularMetrics = await device.getCellularInfo();
cellularImei = cellularMetrics.imei;
cellularIccid = cellularMetrics.iccid;
} catch (err) {
// ignore and move on to get other fields
if (err.message === 'Not supported') {
isControlRequestSupported = false;
}
}
if (!isControlRequestSupported) {
try {
const cellularInfo = await this.getDeviceInfoFromSerial(deviceFromSerialPort);
if (!cellularInfo) {
throw new VError('No data returned from serial port for device info');
}
cellularImei = cellularInfo.imei;
cellularIccid = cellularInfo.iccid;
} catch (err) {
// ignore and move on to get other fields
throw new VError(ensureError(err), 'Could not get device info, ensure the device is in listening mode');
}
}
} catch (err) {
// ignore and move on to get other fields
}


// Print whatever was obtained from the device
this._printIdentifyInfo({
deviceId,
Expand Down Expand Up @@ -1087,5 +1109,95 @@ module.exports = class SerialCommand extends CLICommandBase {
);
process.exit(0);
}

getDeviceInfoFromSerial(device){
return this._issueSerialCommand(device, 'i', IDENTIFY_COMMAND_TIMEOUT)
.then((data) => {
const matches = data.match(/Your (core|device) id is\s+(\w+)/);

if (matches && matches.length === 3){
return matches[2];
}

const electronMatches = data.match(/\s+([a-fA-F0-9]{24})\s+/);

if (electronMatches && electronMatches.length === 2){
const info = { id: electronMatches[1] };
const imeiMatches = data.match(/IMEI: (\w+)/);

if (imeiMatches){
info.imei = imeiMatches[1];
}

const iccidMatches = data.match(/ICCID: (\w+)/);

if (iccidMatches){
info.iccid = iccidMatches[1];
}

return info;
}
});
}

/* eslint-enable max-statements */

/**
* Sends a command to the device and retrieves the response.
* @param devicePort The device port to send the command to
* @param command The command text
* @param timeout How long in milliseconds to wait for a response
* @returns {Promise} to send the command.
* The serial port should not be open, and is closed after the command is sent.
* @private
*/
_issueSerialCommand(device, command, timeout){
if (!device){
throw new VError('No serial port identified');
}
const failDelay = timeout || 5000;

let serialPort;
return new Promise((resolve, reject) => {
serialPort = new SerialPort({ path: device.port, ...SERIAL_PORT_DEFAULTS });
const parser = new SerialBatchParser({ timeout: 250 });
serialPort.pipe(parser);

const failTimer = setTimeout(() => {
reject(timeoutError);
}, failDelay);

parser.on('data', (data) => {
clearTimeout(failTimer);
resolve(data.toString());
});

serialPort.open((err) => {
if (err){
console.error('Serial err: ' + err);
console.error('Serial problems, please reconnect the device.');
reject('Serial problems, please reconnect the device.');
return;
}

serialPort.write(command, (werr) => {
if (werr){
reject(err);
}
});
});
})
.finally(() => {
if (serialPort){
serialPort.removeAllListeners('open');

if (serialPort.isOpen){
return new Promise((resolve) => {
serialPort.close(resolve);
});
}
}
});
}
};

0 comments on commit 685cb56

Please sign in to comment.