Skip to content

Commit

Permalink
Added cash drawer status
Browse files Browse the repository at this point in the history
  • Loading branch information
receiptline committed Jan 9, 2025
1 parent f8e9f35 commit 59dd973
Show file tree
Hide file tree
Showing 5 changed files with 215 additions and 6 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## [1.1.0] - 2025-01-10
### Added
- Cash drawer status

### Fixed
- Buffer length check

## [1.0.5] - 2024-04-14
### Fixed
- README
Expand Down
31 changes: 31 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,31 @@ https://receiptline.github.io/receiptjs/test/print.html
- `offline`: printer is off or offline
- `disconnect`: printer is not connected

## receiptSerial.drawer

The receiptSerial.drawer instance property is a string representing the cash drawer status.

### Value

- A string representing the cash drawer status.
- `drawerclosed`: drawer is closed
- `draweropen`: drawer is open
- `offline`: printer is off or offline
- `disconnect`: printer is not connected

## receiptSerial.invertDrawerState(invert)

The invertDrawerState() instance method inverts cash drawer state.

### Parameters

- `invert` <boolean>
- if true, invert drawer state

### Return value

- None.

## receiptSerial.close()

The close() instance method closes the connection.
Expand Down Expand Up @@ -405,6 +430,9 @@ The on() instance method adds the `listener` function to the listeners array for
- `error`: printer error (except cover open and paper empty)
- `offline`: printer is off or offline
- `disconnect`: printer is not connected
- `drawer`: drawer status updated
- `drawerclosed`: drawer is closed
- `draweropen`: drawer is open
- `listener`
- the listener function

Expand All @@ -429,6 +457,9 @@ The off() instance method removes the `listener` function from the listeners arr
- `error`: printer error (except cover open and paper empty)
- `offline`: printer is off or offline
- `disconnect`: printer is not connected
- `drawer`: drawer status updated
- `drawerclosed`: drawer is closed
- `draweropen`: drawer is open
- `listener`
- the listener function

Expand Down
85 changes: 82 additions & 3 deletions lib/receipt-serial.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,9 @@ const ReceiptSerial = (() => {
paperempty: 'paperempty',
error: 'error',
offline: 'offline',
disconnect: 'disconnect'
disconnect: 'disconnect',
drawerclosed: 'drawerclosed',
draweropen: 'draweropen'
};

// control commands
Expand All @@ -130,7 +132,7 @@ const ReceiptSerial = (() => {
clear: '\x10\x14\x08\x01\x03\x14\x01\x06\x02\x08', // DLE DC4 n d1 d2 d3 d4 d5 d6 d7
siiasb: '\x1da\xff', // GS a n
starasb: '\x1b\x1ea\x01\x17', // ESC RS a n ETB
escasb: '\x1dI\x42\x1dI\x43\x1da\xff' // GS I n GS I n GS a n
escasb: '\x10\x04\x01\x1dI\x42\x1dI\x43\x1da\xff' // DLE EOT n GS I n GS I n GS a n
};

return {
Expand All @@ -150,7 +152,10 @@ const ReceiptSerial = (() => {
paperempty: [],
error: [],
offline: [],
disconnect: []
disconnect: [],
drawer: [],
drawerclosed: [],
draweropen: []
};
// promise resolver
let resolve = () => {};
Expand All @@ -176,6 +181,33 @@ const ReceiptSerial = (() => {
}
}
};
// drawer status
let drawer = state.offline;
// invert drawer status
let invertion = false;
// update drawer status
const updateDrawer = newstatus => {
let d = newstatus;
// invert drawer status
if (invertion) {
switch (d) {
case state.drawerclosed:
d = state.draweropen;
break;
case state.draweropen:
d = state.drawerclosed;
break;
default:
break;
}
}
if (d !== drawer) {
// status event
drawer = d;
dispatch(listeners.drawer, drawer);
dispatch(listeners[drawer]);
}
};
// timer
let timeout = 0;
// printer control language
Expand Down Expand Up @@ -217,6 +249,7 @@ const ReceiptSerial = (() => {
conn.on('close', () => {
// disconnect event
update(state.disconnect);
updateDrawer(state.disconnect);
});
// data event
conn.on('data', data => {
Expand Down Expand Up @@ -245,6 +278,7 @@ const ReceiptSerial = (() => {
const l = ((buffer[0] >> 2 & 0x18) | (buffer[0] >> 1 & 0x07)) + (buffer[1] >> 6 & 0x02);
// check length
if (l <= len) {
// printer
if ((buffer[2] & 0x20) === 0x20) {
// cover open event
update(state.coveropen);
Expand All @@ -260,6 +294,8 @@ const ReceiptSerial = (() => {
else {
// nothing to do
}
// cash drawer
updateDrawer((buffer[2] & 0x04) === 0x04 ? state.draweropen : state.drawerclosed);
// clear data
buffer.splice(0, l);
// clear timer
Expand Down Expand Up @@ -346,6 +382,7 @@ const ReceiptSerial = (() => {
else if ((buffer[0] & 0xf0) === 0xc0) {
// sii: automatic status
if (len > 7) {
// printer
if ((buffer[1] & 0xf8) === 0xd8) {
// cover open event
update(state.coveropen);
Expand All @@ -365,6 +402,8 @@ const ReceiptSerial = (() => {
else {
// nothing to do
}
// cash drawer
updateDrawer((buffer[3] & 0xf8) === 0xd8 ? state.drawerclosed : state.draweropen);
// clear data
buffer.splice(0, 8);
}
Expand All @@ -382,6 +421,7 @@ const ReceiptSerial = (() => {
const l = ((buffer[0] >> 2 & 0x08) | (buffer[0] >> 1 & 0x07)) + (buffer[1] >> 6 & 0x02);
// check length
if (l <= len) {
// printer
if ((buffer[2] & 0x20) === 0x20) {
// cover open event
update(state.coveropen);
Expand All @@ -405,6 +445,8 @@ const ReceiptSerial = (() => {
else {
// nothing to do
}
// cash drawer
updateDrawer((buffer[2] & 0x04) === 0x04 ? state.draweropen : state.drawerclosed);
// clear data
buffer.splice(0, l);
}
Expand All @@ -430,6 +472,7 @@ const ReceiptSerial = (() => {
else if ((buffer[0] & 0x93) === 0x10) {
// escpos: automatic status
if (len > 3 && (buffer[1] & 0x90) === 0 && (buffer[2] & 0x90) === 0 && (buffer[3] & 0x90) === 0) {
// printer
if ((buffer[0] & 0x20) === 0x20) {
// cover open event
update(state.coveropen);
Expand All @@ -449,6 +492,8 @@ const ReceiptSerial = (() => {
else {
// nothing to do
}
// cash drawer
updateDrawer((buffer[0] & 0x04) === 0x04 ? state.drawerclosed : state.draweropen);
// clear data
buffer.splice(0, 4);
}
Expand Down Expand Up @@ -487,12 +532,22 @@ const ReceiptSerial = (() => {
}
// offline event
update(state.offline);
updateDrawer(state.offline);
}
else {
// nothing to do
}
}
}
else if ((buffer[0] & 0x93) === 0x12) {
// escpos: realtime status
// clear timer
clearTimeout(timeout);
// cash drawer
updateDrawer((buffer[0] & 0x97) === 0x16 ? state.drawerclosed : state.draweropen);
// clear data
buffer.shift();
}
else {
// escpos: other
buffer.shift();
Expand All @@ -513,6 +568,30 @@ const ReceiptSerial = (() => {
get status() {
return status;
},
/**
* Cash drawer status.
* @type {string} cash drawer status
*/
get drawer() {
return drawer;
},
/**
* Invert cash drawer state.
* @param {boolean} invert invert cash drawer state
*/
invertDrawerState(invert) {
invertion = !!invert;
switch (drawer) {
case state.drawerclosed:
drawer = state.draweropen;
break;
case state.draweropen:
drawer = state.drawerclosed;
break;
default:
break;
}
},
/**
* Print receipt markdown.
* @param {string} markdown receipt markdown
Expand Down
12 changes: 12 additions & 0 deletions test/print.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
const open = document.querySelector('#open');
const print = document.querySelector('#print');
const close = document.querySelector('#close');
const invert = document.querySelector('#invert');
const body = document.querySelector('body');
const log = msg => {
const div = document.createElement('div');
Expand All @@ -26,6 +27,9 @@
open.onclick = async () => {
if (!conn) {
conn = ReceiptSerial.connect();
conn.on('drawer', status => {
log(status);
});
conn.on('status', status => {
log(status);
});
Expand All @@ -35,6 +39,7 @@
conn.on('disconnect', () => {
conn = null;
});
conn.invertDrawerState(invert.checked);
}
};
print.onclick = async () => {
Expand All @@ -47,6 +52,11 @@
conn.close();
}
};
invert.onchange = () => {
if (conn) {
conn.invertDrawerState(invert.checked);
}
};
}
</script>
</head>
Expand All @@ -63,6 +73,8 @@
<button id="open">Open</button>
<button id="print">Print</button>
<button id="close">Close</button>
<input id="invert" type="checkbox">
<label for="invert">Invert drawer state</label>
<hr>
</body>
</html>
Loading

0 comments on commit 59dd973

Please sign in to comment.