import * as os from "os" ; import { OutputChannel } from "vscode" ; import { CONSTANTS } from "./constants" ; import { logToOutputChannel } from "./extension_utils/utils" ; interface ISerialPortDetail { path : string ; manufacturer : string ; vendorId : string ; productId : string ; } export class SerialPortControl { public static get serialport ( ) : any { if ( ! SerialPortControl . _serialport ) { SerialPortControl . _serialport = require ( "usb-native" ) . SerialPort ; } return SerialPortControl . _serialport ; } public static list ( ) { return new Promise ( ( resolve , reject ) => { SerialPortControl . serialport . list ( ) . then ( ports => resolve ( ports ) , err => reject ( err ) ) ; } ) ; } private static _serialport : any ; private _currentPort : string ; private _currentBaudRate : number ; private _currentSerialPort : any ; public constructor ( port , baudRate , private _outputChannel ) { this . _currentPort = port ; this . _currentBaudRate = baudRate ; } public get isActive ( ) : boolean { return this . _currentSerialPort && this . _currentSerialPort . isOpen ; } public get currentPort ( ) : string { return this . _currentPort ; } public open ( ) { logToOutputChannel ( this . _outputChannel , CONSTANTS . INFO . OPENING_SERIAL_PORT ( this . _currentPort ) ) ; return new Promise ( ( resolve , reject ) => { if ( this . _currentSerialPort && this . _currentSerialPort . isOpen ) { this . _currentSerialPort . close ( ( err ) => { if ( err ) { return reject ( err ) ; } this . _currentSerialPort = null ; return this . open ( ) . then ( ( ) => { resolve ( ) ; } , error => { reject ( error ) ; } ) ; } ) ; } else { this . _currentSerialPort = new SerialPortControl . serialport ( this . _currentPort , { baudRate : this . _currentBaudRate } ) ; this . _outputChannel . show ( ) ; this . _currentSerialPort . on ( "open" , ( ) => { this . _currentSerialPort . write ( CONSTANTS . MISC . SERIAL_MONITOR_TEST_IF_OPEN + os . EOL , ( err ) => { if ( err && ! ( err . message . indexOf ( CONSTANTS . ERROR . COMPORT_UNKNOWN_ERROR ) >= 0 ) ) { logToOutputChannel ( this . _outputChannel , CONSTANTS . ERROR . FAILED_TO_OPEN_SERIAL_PORT ( this . _currentPort ) ) ; logToOutputChannel ( this . _outputChannel , CONSTANTS . ERROR . RECONNECT_DEVICE ) ; reject ( err ) ; } else { logToOutputChannel ( this . _outputChannel , CONSTANTS . INFO . OPENED_SERIAL_PORT ( this . _currentPort ) ) ; resolve ( ) ; } } ) ; } ) ; } this . _currentSerialPort . on ( "data" , ( event ) => { logToOutputChannel ( this . _outputChannel , event . toString ( ) ) ; } ) ; this . _currentSerialPort . on ( "error" , ( error ) => { logToOutputChannel ( this . _outputChannel , error . toString ( ) ) ; } ) ; } ) ; } public changePort ( newPort ) { return new Promise ( ( resolve , reject ) => { if ( newPort === this . _currentPort ) { resolve ( ) ; return ; } this . _currentPort = newPort ; if ( ! this . _currentSerialPort || ! this . isActive ) { resolve ( ) ; return ; } this . _currentSerialPort . close ( ( error ) => { if ( error ) { reject ( error ) ; } else { this . _currentSerialPort = null ; resolve ( ) ; } } ) ; } ) ; } public stop ( ) { return new Promise ( ( resolve , reject ) => { if ( ! this . _currentSerialPort || ! this . isActive ) { resolve ( false ) ; return ; } this . _currentSerialPort . close ( ( error ) => { if ( this . _outputChannel ) { logToOutputChannel ( this . _outputChannel , CONSTANTS . INFO . CLOSED_SERIAL_PORT ( this . _currentPort ) ) ; } this . _currentSerialPort = null ; if ( error ) { reject ( error ) ; } else { resolve ( true ) ; } } ) ; } ) ; } public changeBaudRate ( newBaudRate ) { return new Promise ( ( resolve , reject ) => { this . _currentBaudRate = newBaudRate ; if ( ! this . _currentSerialPort || ! this . isActive ) { resolve ( ) ; return ; } this . _currentSerialPort . update ( { baudRate : this . _currentBaudRate } , ( error ) => { if ( error ) { reject ( error ) ; } else { resolve ( ) ; } } ) ; } ) ; } }