Skip to content

Commit

Permalink
Merge pull request #6 from TransbankDevelopers/fix/resolve-several-bugs
Browse files Browse the repository at this point in the history
Resolve several bugs
  • Loading branch information
mastudillot authored May 25, 2021
2 parents 63f49e9 + bbfe5ba commit 33deabc
Showing 1 changed file with 74 additions and 12 deletions.
86 changes: 74 additions & 12 deletions src/pos.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
const LRC = require("lrc-calculator")
const SerialPort = require("serialport")
const EventEmitter = require('events');
const InterByteTimeout = require("@serialport/parser-inter-byte-timeout")
const responseMessages = require("./responseCodes")
const ACK = 0x06
const FUNCTION_CODE_MULTICODE_SALE = '0271';

module.exports = class POS {
module.exports = class POS extends EventEmitter {

constructor() {
super()
this.currentPort = null
this.connected = false

this.ackTimeout = 2000
this.posTimeout = 150000
this.debugEnabled = false
this.port = null
this.responseAsString = true
this.waiting = false
this.connecting = false;

this.responseCallback = function () {
}
Expand Down Expand Up @@ -77,17 +81,27 @@ module.exports = class POS {

connect(portName = null, baudRate = 115200) {
this.debug("Connecting to " + portName + " @" + baudRate)

return new Promise((resolve, reject) => {
// Block so just one connect command can be sent at a time
if (this.connecting === true) {
reject("Another connect command was already sent and it is still waiting")
return
}

if (this.connected) {
this.debug("Trying to connect to a port while its already connected. Disconnecting... ")
this.disconnect().then(() => {
resolve(this.connect(portName, baudRate))
}).catch(() => {
resolve(this.connect(portName, baudRate))
})
this.connecting = true
return
}

this.connecting = true

this.port = new SerialPort(portName, { baudRate, autoOpen: false })

this.port.open((err) => {
Expand All @@ -100,7 +114,9 @@ module.exports = class POS {
this.parser.on("data", (data) => {

let prettyData = ''
data.forEach(char=>{prettyData += (32 <= char && char<126) ? String.fromCharCode(char) : `{0x${char.toString(16).padStart(2, '0')}}`}, '')
data.forEach(char=>{
prettyData += (32 <= char && char<126) ? String.fromCharCode(char) : `{0x${char.toString(16).padStart(2, '0')}}`
}, '')
this.debug(`🤖 > ${prettyData}`, data)

// Primero, se recibe un ACK
Expand All @@ -124,13 +140,14 @@ module.exports = class POS {
this.connected = true
this.poll().then(() => {
this.currentPort = portName
this.emit('port_opened', this.currentPort);
resolve(true)
}).catch(async (e) => {
this.connected = false
this.waiting = false
this.currentPort = null
try {
await this.port.close();
if(this.port.isOpen) await this.port.close();
} catch (e) {

}
Expand All @@ -144,18 +161,27 @@ module.exports = class POS {
this.currentPort = null
this.waiting = false
this.connected = false
this.emit('port_closed');
})

this.connecting = false
})
}

disconnect() {
return new Promise((resolve, reject) => {

if(!this.port.isOpen) {
resolve(true)
return
}

this.port.close((error) => {
if (error) {
this.debug("Error closing port", error)
reject(error)
} else {
this.debug("Port closed sucessfully")
this.debug("Port closed successfully")
resolve(true);
}
})
Expand All @@ -165,9 +191,15 @@ module.exports = class POS {
}

async autoconnect() {
// Block so just one autoconnect command can be sent at a time
if (this.connecting === true) {
this.debug("It is already trying to connect to a port and we wait for it to finish")
return false
}

let vendors = [
{ vendor: "11ca", product: "0222" }, // Verifone VX520c
{ vendor: "0b00", product: "0054" }, // Ingenico 3500
{ vendor: "0b00", product: "0054" }, // Ingenico DESK3500
]

let availablePorts = await this.listPorts()
Expand All @@ -184,12 +216,14 @@ module.exports = class POS {
this.debug("Trying to connect to " + port.path)
try {
await this.connect(port.path)
this.connecting = false;
return port
} catch (e) {
console.log(e);
}
}

this.connecting = false;
this.debug("Autoconnection failed")
return false
}
Expand All @@ -210,6 +244,7 @@ module.exports = class POS {
// Assert the ack arrives before the given timeout.
let timeout = setTimeout(() => {
this.waiting = false
clearTimeout(responseTimeout)
reject("ACK has not been received in " + this.ackTimeout + " ms.")
}, this.ackTimeout)

Expand All @@ -236,22 +271,30 @@ module.exports = class POS {
}
})

let responseTimeout = setTimeout(() => {
this.waiting = false
reject(`Response of POS has not been received in ${this.posTimeout/1000} seconds`)
}, this.posTimeout)

// Wait for the response and fullfill the Promise
this.responseCallback = (data) => {
clearTimeout(responseTimeout)
let response = data
if (this.responseAsString) {
response = data.toString().slice(1, -2)
}
let functionCode = data.toString().slice(1, 5)
if (functionCode==="0900") { // Sale status messages
if (typeof callback==="function") {
callback(response, data)
}
return
}

if (typeof callback==="function") {
callback(response, data)
if (functionCode==="0900") { // Sale status messages
callback(this.intermediateResponse(response), data)
return
}

if (functionCode==="0261")
callback(response, data)
}

this.waiting = false

resolve(response, data)
Expand Down Expand Up @@ -333,6 +376,15 @@ module.exports = class POS {

salesDetail(printOnPos = false) {
return new Promise((resolve) => {

if(typeof printOnPos !== 'boolean' && typeof printOnPos !== 'string')
return new Promise((resolve, reject) => {
reject("printOnPos must be of type boolean.")
})

if(typeof printOnPos === 'string')
printOnPos = (printOnPos === 'true' || printOnPos === '1') ? true:false

let print = printOnPos ? "0":"1"
let sales = []

Expand Down Expand Up @@ -469,4 +521,14 @@ module.exports = class POS {
}
return response;
}

intermediateResponse(payload) {
let chunks = payload.split("|")
let response = {
responseCode: parseInt(chunks[1]),
responseMessage: this.getResponseMessage(parseInt(chunks[1])),
}

return response;
}
}

0 comments on commit 33deabc

Please sign in to comment.