UNPKG

gps-lib

Version:

Easily interact with NEO-6 series GPS chips and decode location information in your Node.js projects. This library streamlines communication with NEO-6 GPS chips, allowing you to effortlessly extract and utilize precise GPS data in your applications. Harn

271 lines (205 loc) 7.39 kB
var { SerialPort }=require('serialport'); var { ReadlineParser }=require('@serialport/parser-readline'); /* Author: Pallob Kumar Gain */ class serialDeviceHandel{ serial; connected_serial; closeCallback=[]; errorCallback=[]; connectCallback=[]; dataCallback=[]; receiving=true; delimiter; lineParser; waitListenerCallbacks=[]; queue_tasks=[]; queue_busy=false; constructor(delimiter='\r\n'){ this.delimiter=delimiter; } open(port, baud,timeout=3000){ return new Promise((resolve, reject)=>{ this.serial=new SerialPort({path:port,baudRate: baud}, (err)=>{ if(err){ clearTimeout(serial_open_monitor); reject(err); } }); var serial_open_monitor=setTimeout(()=>{ this.serial.close(); reject('Serial Connect Timeout'); },timeout); if(this.serial==null)return reject('Serial port not responding!'); this.serial.on('open',()=>{ clearTimeout(serial_open_monitor); this.connected_serial=this.serial; for(var callback of this.connectCallback){ callback(this.serial); } //console.log({ delimiter:this.delimiter }); this.lineParser = this.serial.pipe(new ReadlineParser({ delimiter:this.delimiter })); this.lineParser.on('data', (line) =>{ if(this.waitListenerCallbacks.length>0){ let currentCallback=this.waitListenerCallbacks.shift(); currentCallback(line); } else if(this.receiving){ for(var callback of this.dataCallback){ callback(line); } } }); this.receiving=true; this.queue_busy=false; resolve(this.serial); }); //serial.on('data',updateBuffer); this.serial.on('close',(...args)=>{ this.connected_serial=null; for(var callback of this.closeCallback){ callback(...args); } }); this.serial.on('error',(...args)=>{ for(var callback of this.errorCallback){ callback(...args); } }); }); } async getList(){ return await SerialPort.list(); } isConnected(){ return this.connected_serial!=null?this.serial.isOpen:false; } close(){ if(this.serial){ this.connected_serial=null; if(this.lineParser)this.lineParser.destroy(); this.receiving=false; this.waitListenerCallbacks.splice(0,this.waitListenerCallbacks.length); this.clearQueueTasks(); this.serial.close(); } } receiverPause(){ //if(this.lineParser)this.lineParser.pause(); this.receiving=false; } receiverResume(){ //if(this.lineParser)this.lineParser.resume(); this.receiving=true; } onClose(callback){ this.closeCallback.push(callback); } onError(callback){ this.errorCallback.push(callback); } onConnect(callback){ this.connectCallback.push(callback); } onReceive(callback){ this.dataCallback.push(callback); } clear(){ return new Promise((resolve,reject)=>{ this.serial.flush((err)=>{ if (err){ return reject(err); } resolve(true); }); }); } clearWaiterCallback(callback_index){ this.waitListenerCallbacks.splice(callback_index,1); } setWaiterCallback(callback){ let current_index=this.waitListenerCallbacks.length; this.waitListenerCallbacks.push(callback); return current_index; } clearQueueTasks(){ for(let {waiter_task:{reject}} of this.queue_tasks){ reject('Serial port closing'); } this.queue_tasks.splice(0,this.queue_tasks.length); this.queue_busy=false; } async kickQueueTasks(){ if(this.queue_busy)return; this.queue_busy=true; while(this.queue_tasks.length>0){ let current_task=this.queue_tasks.shift(); let {write_task,waiter_task:{resolve, reject}}=current_task; try{ resolve(await new Promise(write_task)); } catch(err){ reject(err); } } this.queue_busy=false; } setWriteQueue(write_task){ return new Promise((resolve, reject)=>{ this.queue_tasks.push({ write_task, waiter_task:{resolve, reject} }); this.kickQueueTasks(); }); } write(data,options={}){ if(!('delimiter' in options))options.delimiter='\r\n'; let write_task=(data,options,resolve, reject)=>{ if('receive' in options && options.receive){ let timeout=setTimeout(()=>{ if(waiter_callback)this.clearWaiterCallback(waiter_callback); //if timeout happen clear the callback reject('Serial does not make any response'); },'timeout' in options?options.timeout:1000); let waiter_callback=this.setWaiterCallback(line=>{ clearInterval(timeout); resolve(line); }); } this.serial.write(data,(err)=>{ if (err){ return reject(err); } this.serial.drain((err)=> { if (err) { return reject(err); } else if(!('receive' in options && options.receive)) return resolve(true); }); }); }; return this.setWriteQueue(write_task.bind(this,data,options)); } print(data,options={}){ return this.write(data.toString(),options); } println(data,options={}){ return this.write(data.toString()+"\r\n",options); } set(options,callback){ if(this.serial){ return new Promise((resolve,reject)=>{ var timeChecker=setTimeout(()=>{ reject('Serial setting timeout'); },2000); this.serial.set(options,()=>{ clearTimeout(timeChecker); if(callback)callback(); resolve(true); }); }); } } } module.exports = {serialDeviceHandel};