[IMP] pos_epson_printer: Remove ePOS library

Remove minified ePOS library and replace it with direct calls to the
web server of the printer.

closes odoo/odoo#63403

Taskid: 2417429
Signed-off-by: pimodoo <pimodoo@users.noreply.github.com>
This commit is contained in:
Antoine Prieels
2021-02-23 12:46:54 +00:00
parent 2eb007074c
commit 7f72f5f7ea
6 changed files with 166 additions and 77 deletions
+3
View File
@@ -17,6 +17,9 @@ Use Epson ePOS Printers without the IoT Box in the Point of Sale
'views/point_of_sale_assets.xml',
'views/pos_config_views.xml',
],
'qweb': [
'static/src/xml/epos_templates.xml'
],
'installable': True,
'auto_install': True,
}
File diff suppressed because one or more lines are too long
@@ -2,98 +2,166 @@
odoo.define('pos_epson_printer.Printer', function (require) {
"use strict";
const { Gui } = require('point_of_sale.Gui');
var core = require('web.core');
var PrinterMixin = require('point_of_sale.Printer').PrinterMixin;
var { PrinterMixin, PrintResult, PrintResultGenerator } = require('point_of_sale.Printer');
var QWeb = core.qweb;
var _t = core._t;
var EpsonPrinter = core.Class.extend(PrinterMixin, {
init: function (ip, pos) {
PrinterMixin.init.call(this, arguments);
this.pos = pos;
this.ePOSDevice = new epson.ePOSDevice();
var port = window.location.protocol === 'http:' ? '8008' : '8043';
this.ePOSDevice.connect(ip, port, this.callback_connect.bind(this), {eposprint: true});
},
class EpsonPrintResultGenerator extends PrintResultGenerator {
constructor(address) {
super();
this.address = address;
}
callback_connect: function (resultConnect) {
var deviceId = 'local_printer';
var options = {'crypto' : false, 'buffer' : false};
if ((resultConnect == 'OK') || (resultConnect == 'SSL_CONNECT_OK')) {
this.ePOSDevice.createDevice(deviceId, this.ePOSDevice.DEVICE_TYPE_PRINTER, options, this.callback_createDevice.bind(this));
} else {
Gui.showPopup('ErrorPopup', {
'title': _t('Connection to the printer failed'),
'body': _t('Please check if the printer is still connected, if the configured IP address is correct and if your printer supports the ePOS protocol.'),
});
}
},
callback_createDevice: function (deviceObj, errorCode) {
if (deviceObj === null) {
Gui.showPopup('ErrorPopup', {
'title': _t('Connection to the printer failed'),
'body': _t('Please check if the printer is still connected. Error code: ') + errorCode,
});
return;
}
this.printer = deviceObj;
this.printer.onreceive = function(response){
if (!response.success) {
Gui.showPopup('ErrorPopup', {
'title': _t('Epson ePOS Error'),
'body': _t('An error happened while sending data to the printer. Error code: ') + response.code,
});
IoTActionError() {
var printRes = new PrintResult({
successful: false,
message: {
title: _t('Connection to the printer failed'),
body: _t('Please check if the printer is still connected.'),
}
};
});
if (window.location.protocol === 'https:') {
printRes.message.body += _.str.sprintf(
_t('If you are on a secure server (HTTPS) please make sure you manually accepted the certificate by accessing %s'),
this.address
);
}
return printRes;
}
IoTResultError() {
return new PrintResult({
successful: false,
message: {
title: _t('Printing failed'),
body: _t('Please check if the printer has enough paper and is ready to print.'),
},
});
}
}
var EpsonPrinter = core.Class.extend(PrinterMixin, {
init(ip) {
PrinterMixin.init.call(this, arguments);
var url = window.location.protocol + '//' + ip;
this.address = url + '/cgi-bin/epos/service.cgi?devid=local_printer';
this.printResultGenerator = new EpsonPrintResultGenerator(url);
},
/**
* Transform a (potentially colored) canvas into a monochrome raster image.
* We will use Floyd-Steinberg dithering.
*/
_canvasToRaster(canvas) {
var imageData = canvas.getContext('2d').getImageData(0, 0, canvas.width, canvas.height);
var pixels = imageData.data;
var width = imageData.width;
var height = imageData.height;
var errors = Array.from(Array(width), _ => Array(height).fill(0));
var rasterData = new Array(width * height).fill(0);
for (var y = 0; y < height; y++) {
for (var x = 0; x < width; x++) {
var idx, oldColor, newColor;
// Compute grayscale level. Those coefficients were found online
// as R, G and B have different impacts on the darkness
// perception (e.g. pure blue is darker than red or green).
idx = (y * width + x) * 4;
oldColor = pixels[idx] * 0.299 + pixels[idx+1] * 0.587 + pixels[idx+2] * 0.114;
// Propagate the error from neighbor pixels
oldColor += errors[x][y];
oldColor = Math.min(255, Math.max(0, oldColor));
if (oldColor < 128) {
// This pixel should be black
newColor = 0;
rasterData[y * width + x] = 1;
} else {
// This pixel should be white
newColor = 255;
rasterData[y * width + x] = 0;
}
// Propagate the error to the following pixels, based on
// Floyd-Steinberg dithering.
var error = oldColor - newColor;
if (error) {
if (x < width - 1) {
// Pixel on the right
errors[x + 1][y] += 7/16 * error;
}
if (x > 0 && y < height - 1) {
// Pixel on the bottom left
errors[x - 1][y + 1] += 3/16 * error;
}
if (y < height - 1) {
// Pixel below
errors[x][y + 1] += 5/16 * error;
}
if (x < width - 1 && y < height - 1) {
// Pixel on the bottom right
errors[x + 1][y + 1] += 1/16 * error;
}
}
}
}
return rasterData.join('');
},
/**
* Create the print request for webPRNT from a canvas
* Base 64 encode a raster image
*/
_encodeRaster(rasterData) {
var encodedData = '';
for(var i = 0; i < rasterData.length; i+=8){
var sub = rasterData.substr(i, 8);
encodedData += String.fromCharCode(parseInt(sub, 2));
}
return btoa(encodedData);
},
/**
* Create the raster data from a canvas
*
* @override
*/
process_canvas: function (canvas) {
if (this.printer) {
this.printer.addTextAlign(this.printer.ALIGN_CENTER);
this.printer.addImage(canvas.getContext('2d'), 0, 0, canvas.width, canvas.height);
this.printer.addCut();
}
process_canvas(canvas) {
var rasterData = this._canvasToRaster(canvas);
var encodedData = this._encodeRaster(rasterData);
return QWeb.render('ePOSPrintImage', {
image: encodedData,
width: canvas.width,
height: canvas.height,
});
},
/**
* @override
*/
open_cashbox: function () {
if (this.printer) {
this.printer.addPulse();
this.printer.send();
}
open_cashbox() {
var pulse = QWeb.render('ePOSDrawer');
this.send_printing_job(pulse);
},
/**
* @override
*/
send_printing_job: function () {
if (this.printer) {
this.printer.send();
return {
result: true
};
}
async send_printing_job(img) {
const res = await $.ajax({
url: this.address,
method: 'POST',
data: img,
});
return $(res).find('response').attr('success') === 'true';
},
//--------------------------------------------------------------------------
// Handlers
//--------------------------------------------------------------------------
/**
* Not applicable to Epson ePOS
* @override
*/
_onIoTActionFail: function () {},
_onIoTActionResult: function () {},
});
return EpsonPrinter;
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
<t t-name="ePOSTemplate">
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<epos-print xmlns="http://www.epson-pos.com/schemas/2011/03/epos-print">
<t t-raw="0"/>
</epos-print>
</s:Body>
</s:Envelope>
</t>
<t t-name="ePOSPrintImage">
<t t-call="ePOSTemplate">
<image t-att-width="width" t-att-height="height" align="center" t-esc="image"/>
<cut type="feed"/>
</t>
</t>
<t t-name="ePOSDrawer">
<t t-call="ePOSTemplate">
<pulse/>
</t>
</t>
</templates>
@@ -4,7 +4,6 @@
<xpath expr="." position="inside">
<script type="text/javascript" src="/pos_epson_printer/static/src/js/pos_epson_printer.js"></script>
<script type="text/javascript" src="/pos_epson_printer/static/src/js/printers.js"></script>
<script type="text/javascript" src="/pos_epson_printer/static/lib/epos-2.12.0.js"></script>
</xpath>
</template>
</odoo>
@@ -16,7 +16,7 @@ var _super_posmodel = models.PosModel.prototype;
models.PosModel = models.PosModel.extend({
create_printer: function (config) {
if (config.printer_type === "epson_epos") {
return new EpsonPrinter(config.epson_printer_ip , posmodel);
return new EpsonPrinter(config.epson_printer_ip);
} else {
return _super_posmodel.create_printer.apply(this, arguments);
}