Open WillCHansen opened 7 years ago
Hey, i tried your solution, but it does not work :-(
I tried the following code:
var printer = ipp.Printer(MY_URL);
var msg = new Buffer(
'02000002' +
'00000001' + //reqi
'01' + //operation-attributes-tag
//blah blah the required bloat of this protocol
// '470012617474726962757465732d6368617273657400057574662d3848001b617474726962757465732d6e61747572616c2d6c616e67756167650002656e' +
'03' //end-of-attributes-tag
+
'02' + //job attributes tag
'34' + //begin collection
'0009' + //length
'6d656469612d636f6c' + //media-col
'0000' + //value length
'4a' + //collection entry
'0000' + //name length
'000c' + //value length
'6d656469612d736f75726365' + //media-source
'44' + // keyword tag
'0000' + //name length
'0006' + //value length
'747261792d32' + //tray-2
'37' + //end of collection
'00000000' + //name length and value length
'03'
, 'hex');
var file = ipp.parse(msg);
file.data = data;
printer.execute("Print-Job", file, function (err, res) {
console.log("Printed: " + res.statusCode);
});
But the display on my printer still shows the message i need to put paper in the first paper tray. And where did you find the spec you mentioned?
Running the message through "printer.execute" triggers the serialize function and causes the same error again. Use ipp.request. williamkapke references the spec throughout the package but here's a link to some helpful info https://tools.ietf.org/html/rfc2911
var PDFDocument = require("pdfkit");
let fs = require('fs')
var ipp = require('ipp');
var uri = "http://10.1.205.71";
var msg = new Buffer(
'0200'+ //Version
'000201e6d5f2'+
'01'+ //Operation attributes tag (your information in the Operation attributes might be different)
'47'+ //charset tag
'0012'+ //length
'617474726962757465732d63686172736574'+ //attributes-charset
'0005'+ //length
'7574662d38'+ //utf-8
'48'+ //natural language tag
'001b'+ //length
'617474726962757465732d6e61747572616c2d6c616e6775616765'+//attributes-natural-language
'0002'+//length
'656e'+ //en
'45'+ // URI tag
'000b'+ //length
'7072696e7465722d757269'+ //printer-uri
'0012'+//length
'687474703a2f2f31302e312e3230352e3731'+//http://10.1.205.71
'49'+ //mimeMediaType tag
'000f'+ //length
'646f63756d656e742d666f726d6174'+ //document format
'000f'+ //length
'6170706c69636174696f6e2f706466'+ //application/pdf
'02'+ //job attributes tag
'34'+ //begin collection
'0009'+ //length
'6d656469612d636f6c'+ //media-col
'0000'+ //value length
'4a'+ //collection entry
'0000'+ //name length
'000c'+ //value length
'6d656469612d736f75726365'+ //media-source
'44'+ // collection entry
'0000'+ //name length
'0006'+ //value length
'747261792d32'+ //tray-2
'37'+ //end of collection
'00000000'+ //name length and value length
'03', 'hex');
var doc = new PDFDocument;
doc.text("Hello World");
var buffers = [];
doc.on('data', buffers.push.bind(buffers));
doc.on('end', function(){
var buf = Buffer.concat(buffers);
var catBuf = Buffer.concat([msg, buf]);
ipp.request(uri, catBuf, function(err, res){
if(err){
return console.log(err);
}
console.log(JSON.stringify(res,null,2));
});
});
doc.end();
Thanks for the fast reply :-) I tried it, but now i got an error message in the console:
{
Error
at new IppResponseError (/Users/alex/dev/print/printing/node_modules/ipp/lib/request.js:72:17)
at ClientRequest.<anonymous> (/Users/alex/dev/print/printing/node_modules/ipp/lib/request.js:40:8)
at Object.onceWrapper (events.js:293:19)
at emitOne (events.js:96:13)
at ClientRequest.emit (events.js:191:7)
at HTTPParser.parserOnIncomingClient [as onIncoming] (_http_client.js:522:21)
at HTTPParser.parserOnHeadersComplete (_http_common.js:99:23)
at Socket.socketOnData (_http_client.js:411:20)
at emitOne (events.js:96:13)
at Socket.emit (events.js:191:7)
name: 'IppResponseError',
statusCode: 400,
message: 'Received unexpected response status 400 from the printer',
stack: 'Error\n at new IppResponseError (/Users/alex/dev/print/printing/node_modules/ipp/lib/request.js:72:17)\n at ClientRequest.<anonymous> (/Users/alex/dev/print/printing/node_modules/ipp/lib/request.js:40:8)\n at Object.onceWrapper (events.js:293:19)\n at emitOne (events.js:96:13)\n at ClientRequest.emit (events.js:191:7)\n at HTTPParser.parserOnIncomingClient [as onIncoming] (_http_client.js:522:21)\n at HTTPParser.parserOnHeadersComplete (_http_common.js:99:23)\n at Socket.socketOnData (_http_client.js:411:20)\n at emitOne (events.js:96:13)\n at Socket.emit (events.js:191:7)' }
400 'response'
To my setup: The printer itself does not support IPP directly. I shared the printer on my MacbookPro, which provided an IPP service for all shared printers. Could it be, that this setup causes this error? Or do you have another idea?
Sorry, I'm not sure. I only have limited experience with my setup here at work.
I would try a get attributes request and make sure that the commands you're sending are supported.
I also tried another printer, but i got the same error message.
I have totally forgotten to say I opened a Stackoverflow question for this problem a few days ago.
https://stackoverflow.com/questions/44144159/cannot-print-on-another-paper-tray-via-ipp
Ok- this took me forever to dive in to. My deepest apologies.
Such amazing input provided by ya'll. Thank you so much.
Yup: collection serialization has been been broken. There were 2 issues that have surfaced.
1) it was incorrectly using memberAttrName
(0x4a) for all values.
2) media-col
did not have it's members defined (see https://tools.ietf.org/html/rfc3382#section-5.1)
I pushed a fix c5821bb45b0ff12c6118ab251a84feeb3ff1b5e0 that I believe corrects the issues. I have tested as much as I can with my available resource- but, with so many printers & options out there; It's really hard to said 100% that it's bug free now. So please try to test again whenever you have the chance.
As a basic test, I used the example from the RFC and verified byte by byte (as you did!) the data.
Here's the test script:
var ipp = require('./');
var data = ipp.serialize({
"operation-attributes-tag": {
"attributes-charset": "utf-8",
"attributes-natural-language": "en",
"printer-uri": 'noooooo',
"document-format": "application/pdf"
},
"job-attributes-tag": {
"media-col":
{
"media-color": 'blue',
"media-size":
{
"x-dimension": 6,
"y-dimension": 4
}
},
"copies": "2"
},
data: new Buffer([])
})
console.log(data.toString("hex"))
Here's what the RFC says the output should be:
Octets | Symbolic Value | Protocol field | comments |
---|---|---|---|
0x34 | begCollection | value-tag | beginning of the "media-col" collection attribute |
0x0009 | name-length | length of (collection) attribute name | |
media-col | media-col | name | name of (collection) attribute |
0x0000 | value-length | defined to be 0 for this type | |
no value (since value-length was 0) | |||
0x4A | memberAttrName | value-tag | starts a new member attribute: "media-color" defined to be 0 for this type, so part of 1setOf |
0x0000 | name-length | ||
no name (since name-length was 0) | |||
0x000B | value-length | length of "media-color" keyword | |
media-color | media-color | value | value is name of 1st member attribute |
0x44 | keyword type | value-tag | keyword type |
0x0000 | name-length | 0 indicates 1setOf | |
no name (since name-length was 0) | |||
0x0004 | value-length | ||
blue | blue | value | value of 1st member attribute |
0x4A | memberAttrName | value-tag | starts a new member attribute: "media-size" |
0x0000 | name-length | defined to be 0 for this type, so part of 1setOf | |
no name (since name-length was 0) | |||
0x000A | value-length | length of "media-size" keyword | |
media-size | media-size | value | Name of 2nd member attribute |
0x34 | begCollection | value-tag | Beginning of the "media-size" collection attribute which is a sub-collection |
0x0000 | name-length | 0 indicates 1setOf | |
no name (since name-length was 0) | |||
0x0000 | value-length | collection attribute names have no value | |
no value (since value-length was 0) | |||
0x4A | memberAttrName | value-tag | starts a new member attribute: "x-dimension" |
no name (since name-length was 0) | |||
0x000B | value-length | length of "x-dimension" keyword | |
x-dimension | x-dimension | value | name of 1st sub-collection member attribute |
0x21 | integer type | value-tag | attribute type |
0x0000 | name-length | 0 indicates 1setOf | |
no name (since name-length was 0) | |||
0x0004 | value-length | length of an integer = 4 | |
0x0006 | value | value of 1st sub-collection member attribute | |
0x4A | memberAttrName | value-tag | starts a new member attribute: "y-dimension" |
0x0000 | name-length | defined to be 0 for this type, so part of 1setOf | |
no name (since name-length was 0) | |||
0x000B | value-length | length of the "y-dimension" keyword | |
y-dimension | y-dimension | value | name of 2nd sub-collection member attribute |
0x21 | integer type | value-tag | attribute type |
0x0000 | name-length | 0 indicates 1setOf | |
no name (since name-length was 0) | |||
0x0004 | value-length | length of an integer = 4 | |
0x0004 | value | value of 2nd sub-collection member attribute | |
0x37 | endCollection | value-tag | end of the sub-collection |
0x0000 | name-length | defined to be 0 for this type, so part of 1setOf | |
no name (since name-length was 0) | |||
0x0000 | value-length | defined to be 0 for this type | |
no value (since value-length was 0) | |||
0x37 | endCollection | value-tag | end of the 1st collection value in 1setOf |
0x0000 | name-length | defined to be 0 for this type, so part of 1setOf | |
no name (since name-length was 0) | |||
0x0000 | value-length | defined to be 0 for this type | |
no value (since value-length was 0) |
This is linked to the other issues of not being able to select the tray.
var msg = { "job-attributes-tag": { "media-col": { "media-source": "tray-2" } }}
Serializes to:
'02'+ //job attributes tag '34'+ //begin collection '0009'+ //length '6d656469612d636f6c'+ //media-col '0000'+ //value length '4a'+ //collection entry '0000'+ //name length '000c'+ //value length '6d656469612d736f75726365'+ //media-source '4a'+ // collection entry '0000'+ //name length '0006'+ //value length '747261792d32'+ //tray-2 '37'+ //end of collection '00000000'+ //name length and value length '03'
According to the spec
The issue is that the "0x4a" tag is being applied to the second entry in the collection, but it should only be applied to the parent name. The correct message is below.
'02'+ //job attributes tag '34'+ //begin collection '0009'+ //length '6d656469612d636f6c'+ //media-col '0000'+ //value length '4a'+ //collection entry '0000'+ //name length '000c'+ //value length '6d656469612d736f75726365'+ //media-source '44'+ // keyword tag '0000'+ //name length '0006'+ //value length '747261792d32'+ //tray-2 '37'+ //end of collection '00000000'+ //name length and value length '03'
Please let me know if you need any additional information.