Skip to content

Commit

Permalink
Interfaces
Browse files Browse the repository at this point in the history
- Abstracted printer interface
- Support for printer (https://www.npmjs.com/package/printer)
- Support for electron-printer (https://www.npmjs.com/package/electron-printer)
- Tested with more printers
- Easy to use interface configuration strings (tcp://, printer:, \\.\COM1)
  • Loading branch information
buffcode committed Sep 27, 2017
1 parent 44e6a80 commit 5e08969
Show file tree
Hide file tree
Showing 6 changed files with 204 additions and 62 deletions.
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,19 @@ printer.printBarcode(data, type, settings);
| 78 | GS1 DataBar Expanded | 0 – 9, A – D, a – d, SP, !, ", %, $, ', (, ), *, +, ,, -, ., /, :, ;, <, =, >, ?, _, { | 2 - 255 |


### Interfaces
Example configuration strings for the `interface` option:
* e.g. `\\.\COM1`
On Windows to open a serial or parallel port. (Be sure to escape the string like that: `"interface": "\\\\.\\COM1"`)
* `tcp://192.168.0.99:9100`
Network print
* `printer:auto`
Windows node [printer](https://www.npmjs.com/package/printer) wrapper (Thanks to [kkaptan](https://github.com/Klemen1337/node-thermal-printer/issues/7#issuecomment-287342297)). Also supports [electron-printer](https://www.npmjs.com/package/electron-printer).
Instead of `auto` (which will select the first raw-only printer), a specific printer name may be used: `printer:EPSON TM-T88V Receipt`

### Usage Tips
`characterSet` may be configured with `"raw"`, so no replacement is done at all.

### Docs
- STAR: http://www.starmicronics.com/support/mannualfolder/starline_cm_rev1.15_en.pdf
- EPSON: https://reference.epson-biz.com/modules/ref_escpos/index.php
Expand All @@ -176,3 +189,5 @@ printer.printBarcode(data, type, settings);
### Tested printers:
- Star TSP700
- Rongta RP80US
- EPSON TM-T88V
- Posman BTP-R880NP (Type "epson")
37 changes: 37 additions & 0 deletions interfaces/file.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
var fs = require("fs");

var writeFile = require("write-file-queue")({
retries : 1000, // number of write attempts before failing
waitTime : 200 // number of milliseconds to wait between write attempts
//, debug : console.error // optionally pass a function to do dump debug information to
});

function File(path) {
this.path = path;
}
File.prototype.execute = function(buffer, cb) {
writeFile(this.path, buffer, function (err) {
if (err) {
if ("function" === typeof cb) {
cb("Print failed: " + err);
} else {
console.error("Print failed", err);
}
} else {
if ("function" === typeof cb) {
cb( null );
} else {
console.log("Print done");
}
}
});
};
File.prototype.isPrinterConnected = function(exists){
if (this.path){
fs.exists(this.path, function(ex){
exists(ex);
});
}
};

module.exports = File;
22 changes: 22 additions & 0 deletions interfaces/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const parseNet = /^tcp:\/\/([^\/:]+)(?::(\d+))?\/?$/i;
const parsePrinter = /^printer:([^\/]+)(?:\/([\w-]*))?$/i;

function getInterface(uri) {
if (typeof uri === "object") {
return uri;
}
const net = parseNet.exec(uri);
if (net) {
const Mod = require('./net');
return new Mod(net[1], net[2]);
}
const printer = parsePrinter.exec(uri);
if (printer) {
const Mod = require('./printer');
return new Mod(printer[1], printer[2]);
}

const Mod = require('./file');
return new Mod(uri);
}
module.exports = getInterface;
53 changes: 53 additions & 0 deletions interfaces/net.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
var net = require("net");

function NetPrint(host, port) {
this.timeout = 3000;
this.host = host;
this.port = port || 9100;
}
NetPrint.prototype.execute = function(buffer, cb) {
var printer = net.connect({
host : this.host,
port : this.port,
timeout: this.timeout
}, function() {
printer.write(buffer, null, function () {
if (typeof cb !== "undefined") {
cb(null);
}
printer.end();
});
});
printer.on('error', function (err) {
if (typeof cb !== "undefined") {
cb(err);
}
printer.end();
});
printer.on('timeout', function () {
if (typeof cb !== "undefined") {
cb("Error: Socket Timeout");
}
printer.end();
});
};
NetPrint.prototype.isPrinterConnected = function(exists){
var printer = net.connect({
host : this.host,
port : this.port,
timeout: this.timeout
}, function() {
exists(true);
printer.end();
});
printer.on('error', function (err) {
exists(false);
printer.end();
});
printer.on('timeout', function () {
exists(false);
printer.end();
});
};

module.exports = NetPrint;
49 changes: 49 additions & 0 deletions interfaces/printer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
const electron = typeof process !== 'undefined' && process.versions && !!process.versions.electron;

function PrinterIface(printerName, moduleName) {
this.name = printerName;
if (moduleName && typeof moduleName === "object") {
this.driver = moduleName;
} else {
this.driver = require(moduleName || (electron ? "electron-printer" : "printer"));
}
}
PrinterIface.prototype.getPrinterName = function() {
var name = this.name;
if (!name || name === "auto") {
const pl = this.driver.getPrinters().filter(function(p) { return p.attributes.indexOf("RAW-ONLY") > -1 });
if (pl.length > 0) {
name = pl[0].name;
}
}
if (!name || name === "auto") {
throw "A RAW-ONLY Printer could not be detected. Please configure a Printer-Name";
}
return name;
};
PrinterIface.prototype.isPrinterConnected = function(exists){
if (this.driver.getPrinter(this.getPrinterName())) {
exists(true);
} else {
exists(false);
}
};
PrinterIface.prototype.execute = function(buffer, cb) {
this.driver.printDirect({
data: buffer,
printer: this.getPrinterName(),
type: "RAW",
success: function(jobID) {
if (typeof cb === "function") {
cb(null);
}
},
error: function(err) {
if (typeof cb === "function") {
cb(err);
}
}
});
};

module.exports = PrinterIface;
90 changes: 28 additions & 62 deletions lib/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,15 @@ var fs = require('fs'),
net = require("net"),
PNG = require('node-png').PNG,
star = require('./star'),
epson = require('./epson');

var writeFile = require('write-file-queue')({
retries : 1000, // number of write attempts before failing
waitTime : 200 // number of milliseconds to wait between write attempts
//, debug : console.error // optionally pass a function to do dump debug information to
});
epson = require('./epson'),
getInterface = require("./interfaces");

var printerTypes = {
EPSON: 'epson',
STAR: 'star'
};

var iface = null;
var config = undefined;
var buffer = null;
var printerConfig;
Expand All @@ -29,6 +25,8 @@ module.exports = {
config = require('../configs/epsonConfig');
}

iface = getInterface(initConfig.interface);

if(!initConfig.width) initConfig.width = 48;
if(!initConfig.characterSet) initConfig.characterSet = "SLOVENIA";
if(initConfig.removeSpecialCharacters === undefined) initConfig.removeSpecialCharacters = false;
Expand All @@ -40,32 +38,18 @@ module.exports = {


execute: function(cb){
if(printerConfig.ip){
var printer = net.connect({
host : printerConfig.ip,
port : printerConfig.port
});
printer.write(buffer);
printer.end();

} else {
writeFile(printerConfig.interface , buffer, function (err) {
if (err) {
if ("function" === typeof cb) {
cb("Print failed: " + err);
} else {
console.error("Print failed", err);
}
} else {
buffer = null;
if ("function" === typeof cb) {
cb( null );
} else {
console.log("Print done");
}
iface.execute(buffer, function (err) {
if (!err) {
buffer = null;
if (typeof cb === "function") {
cb(null);
}
});
}
} else {
if (typeof cb === "function") {
cb(err);
}
}
});
},


Expand Down Expand Up @@ -327,11 +311,7 @@ module.exports = {


isPrinterConnected: function(exists){
if(printerConfig.interface){
fs.exists(printerConfig.interface, function(ex){
exists(ex);
});
}
iface.exists(exists);
},


Expand Down Expand Up @@ -444,32 +424,18 @@ module.exports = {


// ------------------------------ RAW ------------------------------
raw: function(text,cb) {
if (printerConfig.ip) {
var printer = net.connect({
host: printerConfig.ip,
port: printerConfig.port
});
printer.write(text);
printer.end();

} else {
writeFile(printerConfig.interface, text, function (err) {
if (err) {
if ('function' == typeof cb) {
cb("Print failed: " + err);
} else {
console.error("Print failed", err);
}
} else {
if ('function' == typeof cb) {
cb("Print failed: " + err);
} else {
console.log("Print done");
}
raw: function(text, cb) {
iface.execute(text, function (err) {
if (!err) {
if (typeof cb === "function") {
cb(null);
}
});
}
} else {
if (typeof cb === "function") {
cb(err);
}
}
});
}
};

Expand Down

0 comments on commit 5e08969

Please sign in to comment.