ioBroker.js-controller icon indicating copy to clipboard operation
ioBroker.js-controller copied to clipboard

Binary states - avoid buffer.toString() / console.log() - write buffer contents directly to process.stdout

Open klein0r opened this issue 2 years ago • 6 comments

Tested with js-controller 4.0.23

Test Script (PNG file header):

await this.setForeignObjectNotExistsAsync('0_userdata.0.testBinary', {
    type: 'state',
    common: {
        name: 'Test Binary',
        type: 'file',
        role: 'value',
        read: true,
        write: false,
    },
    native: {},
});

const uint8 = new Uint8Array([0x50, 0x89, 0x47, 0x4e, 0x0a, 0x0d, 0x0a, 0x1a, 0x00, 0x00, 0x0d, 0x00, 0x48, 0x49, 0x52, 0x44]);
const testData = Buffer.from(uint8);

this.setForeignBinaryState('0_userdata.0.testBinary', testData, () => {
    this.log.debug('saved');
});

read with hex option

./iobroker state getBinary 0_userdata.0.testBinary --encoding hex
5089474e0a0d0a1a00000d0048495244

✅ ok

read with base64 option

./iobroker state getBinary 0_userdata.0.testBinary --encoding base64 | base64 -d | hexdump -C
00000000  50 89 47 4e 0a 0d 0a 1a  00 00 0d 00 48 49 52 44  |P.GN........HIRD|

✅ ok

read with binary option

./iobroker state getBinary 0_userdata.0.testBinary --encoding binary | hexdump -C
00000000  50 c2 89 47 4e 0a 0d 0a  1a 00 00 0d 00 48 49 52  |P..GN........HIR|
00000010  44 0a                                             |D.|

⚠️ ???

klein0r avatar May 19 '22 09:05 klein0r

Is it possible that js-controller uses the "binary" encoding for this? AFAIK this is some weird text encoding and does NOT result in the raw buffer

AlCalzone avatar May 19 '22 09:05 AlCalzone

Yes, this is exactly the case, encoding is passed as given https://github.com/ioBroker/ioBroker.js-controller/blob/1fe5a1e66dc343f146a54a3b5476add09aa97416/packages/cli/src/lib/cli/cliStates.js#L142

foxriver76 avatar May 19 '22 10:05 foxriver76

Okay, seems like that option is really strange:

https://stackoverflow.com/questions/52564196/buffer-tostringbinary-adds-new-characters

https://nodejs.org/docs/latest-v16.x/api/buffer.html#buffers-and-character-encodings

'binary': Alias for 'latin1'. See binary strings for more background on this topic. The name of this encoding can be very misleading, as all of the encodings listed here convert between strings and binary data. For converting between strings and Buffers, typically 'utf8' is the right choice.

klein0r avatar May 19 '22 10:05 klein0r

Why is toString used there? Maybe it would be a better option to write the buffer contents to stdout?

const uint8 = new Uint8Array([0x50, 0x89, 0x47, 0x4e, 0x0a, 0x0d, 0x0a, 0x1a, 0x00, 0x00, 0x0d, 0x00, 0x48, 0x49, 0x52, 0x44]);
const testData = Buffer.from(uint8);

console.log(testData.toString('binary'));

node testBuffer.js | hexdump -C
00000000  50 c2 89 47 4e 0a 0d 0a  1a 00 00 0d 00 48 49 52  |P..GN........HIR|
00000010  44 0a                                             |D.|
00000012

const uint8 = new Uint8Array([0x50, 0x89, 0x47, 0x4e, 0x0a, 0x0d, 0x0a, 0x1a, 0x00, 0x00, 0x0d, 0x00, 0x48, 0x49, 0x52, 0x44]);
const testData = Buffer.from(uint8);

process.stdout.write(testData);

node testBuffer.js | hexdump -C
00000000  50 89 47 4e 0a 0d 0a 1a  00 00 0d 00 48 49 52 44  |P.GN........HIRD|
00000010

klein0r avatar May 19 '22 10:05 klein0r

Ok, then the "fix" is easy ... when "necoding" is set we use "toString" and if no encoding is set we putput the buffer ...

Apollon77 avatar May 19 '22 11:05 Apollon77

As we implemetned this is controller 4 we were sure that binary means binary :-((

Apollon77 avatar May 19 '22 11:05 Apollon77