diff --git a/lib/bindings/win32-sn-parser.js b/lib/bindings/win32-sn-parser.js new file mode 100644 index 000000000..f92b8cc1b --- /dev/null +++ b/lib/bindings/win32-sn-parser.js @@ -0,0 +1,20 @@ +'use strict'; + +const PARSERS = [ + /USB\\(?:.+)\\(.+)/, + /FTDIBUS\\(?:.+)\+(.+?)A?\\.+/ +]; + +module.exports = function(pnpId) { + if (!pnpId) { + return null; + } + for (let index = 0; index < PARSERS.length; index++) { + const parser = PARSERS[index]; + const sn = pnpId.match(parser); + if (sn) { + return sn[1]; + } + } + return null; +}; diff --git a/lib/bindings/win32.js b/lib/bindings/win32.js index 333167f8b..4f0a39563 100644 --- a/lib/bindings/win32.js +++ b/lib/bindings/win32.js @@ -2,6 +2,7 @@ const binding = require('bindings')('serialport.node'); const BaseBinding = require('./base'); const promisify = require('../util').promisify; +const serialNumParser = require('./win32-sn-parser'); class WindowsBinding extends BaseBinding { static list() { @@ -9,9 +10,10 @@ class WindowsBinding extends BaseBinding { // Grab the serial number from the pnp id ports.forEach(port => { if (port.pnpId) { - const parts = port.pnpId.match(/USB\\(.+)\\(.+)/); - if (!parts) { return } - port.serialNumber = parts.pop(); + const serialNumber = serialNumParser(port.pnpId); + if (serialNumber) { + port.serialNumber = serialNumber; + } } }); return ports; diff --git a/test/bindings-win32-sn-parser.js b/test/bindings-win32-sn-parser.js new file mode 100644 index 000000000..b760d47c8 --- /dev/null +++ b/test/bindings-win32-sn-parser.js @@ -0,0 +1,40 @@ +'use strict'; + +const serialNumParser = require('../lib/bindings/win32-sn-parser'); + +const devices = { + 'FTDI Device': { + pnpId: 'FTDIBUS\\VID_0403+PID_6015+DO004ZB7A\\0000', + serialNumber: 'DO004ZB7' + }, + 'Arduino Mega': { + pnpId: 'USB\\VID_2341&PID_0042\\85531303630351C081D2', + serialNumber: '85531303630351C081D2' + }, + 'Atlas Scientific EZO-RGB Sensor': { + pnpId: 'FTDIBUS\\VID_0403+PID_6015+DJ1XJE67A\\0000', + serialNumber: 'DJ1XJE67' + }, + 'Gearmo FTDI2-LED USB RS-232 Serial Adapter': { + pnpId: 'FTDIBUS\\VID_0403+PID_6001+AL1WHZWFA\\0000', + serialNumber: 'AL1WHZWF' + }, + 'Arducam Nano V3.0 (Arduino Nano with FTDI)': { + pnpId: 'FTDIBUS\\VID_0403+PID_6001+A51MAMMEA\\0000', + serialNumber: 'A51MAMME' + }, + 'Pretend Device with an unknown pnp id': { + pnpId: 'WATEVER\\Whoever\\However!', + serialNumber: null + } +}; + +describe('serialNumParser', () => { + Object.keys(devices).forEach(device => { + it(`parses pnp id for ${device}`, () => { + const pnpId = devices[device].pnpId; + const serialNumber = devices[device].serialNumber; + assert.equal(serialNumParser(pnpId), serialNumber); + }); + }); +});