sebi2k1 / node-can

NodeJS SocketCAN extension
222 stars 72 forks source link

Can not read 32bit #40

Closed huseyinkozan closed 6 years ago

huseyinkozan commented 6 years ago

Hi, I tried to read 32 bit but it returns zero. Can you change the test function with below and confirm?

exports['little_endian_decode'] = function(test) {
    data = new Buffer([0xDE, 0xAD, 0xBE, 0xEF, 0xCA, 0xFE, 0xBA, 0xBE]);

    test.equals(signals.decode_signal(data, 0, 8, true, false), 0xDE);
    test.equals(signals.decode_signal(data, 0, 12, true, false), 0xDDE);
    test.equals(signals.decode_signal(data, 0, 16, true, false), 0xADDE);
    test.equals(signals.decode_signal(data, 0, 24, true, false), 0xBEADDE);
    test.equals(signals.decode_signal(data, 0, 32, true, false), 0xEFBEADDE);

    test.equals(signals.decode_signal(data, 12, 8, true, false), 0xEA);
    test.equals(signals.decode_signal(data, 12, 12, true, false), 0xBEA);
    test.equals(signals.decode_signal(data, 12, 20, true, false), 0xEFBEA);
    test.equals(signals.decode_signal(data, 12, 36, true, false), 0xCAEFBEA);

    test.equals(signals.decode_signal(data, 0, 1, true, false), 0);
    test.equals(signals.decode_signal(data, 1, 1, true, false), 1);
    test.equals(signals.decode_signal(data, 2, 1, true, false), 1);
    test.equals(signals.decode_signal(data, 3, 1, true, false), 1);

    test.done();
}

Also, tried to fix the return value type, but no luck:


    Local<Number> retval;
    uint64_t val = _getvalue(data, offset, bitLength, endianess);

    // Value shall be interpreted as signed (2's complement)
    if (isSigned && val & (1 << (bitLength - 1))) {
        int64_t tmp = -1 * (~((UINT64_MAX << bitLength) | val) + 1);
        retval = Number::New(Isolate::GetCurrent(), tmp);
    } else {
        retval = Number::New(Isolate::GetCurrent(), val);
    }

    info.GetReturnValue().Set(retval);
huseyinkozan commented 6 years ago

I need 32bit for location info:

    <!-- 65267 -->
    <Message id="0xFEF3" name="msg_loc" format="extended">
     <Producer>
       <NodeRef id="1"/>
     </Producer>
     <Signal name="lat" offset="0" length="32" endianess="little">
       <Value type="signed"/>
     </Signal>
     <Signal name="lng" offset="32" length="32" endianess="little">
       <Value type="signed"/>
     </Signal>
    </Message>
huseyinkozan commented 6 years ago

Are there any reason to avoid Buffer::readInt16LE() and other Buffer functions ?

sebi2k1 commented 6 years ago

The Buffer function usually don't work because it is quite common in CAN messages that the signal are not on byte boundaries and have an odd length (e.g. 12bit spanned in 2 bytes).

huseyinkozan commented 6 years ago

Maybe we can do bit ops at js level. Like this lib : https://github.com/inolen/bit-buffer

huseyinkozan commented 6 years ago

Anyway, I can read buffer directly from channel message. You can close issue if you want.

Here how I am reading:

function onMessage(msg) {
  if (msg == undefined) return;
  if (msg.rtr) return;
  switch (msg.id) {
    case 65267:
      console.log("onMessage()");
      console.log("  data:", msg.data);
      console.log("  lat :", msg.data.readInt32LE(0) * Number("1e-7"));
      console.log("  lng :", msg.data.readInt32LE(4) * Number("1e-7"));
      break;
    default:
  }
}

Here the output:

onMessage()
  data: <Buffer f2 99 95 95 1d d6 ce 49>
  lat : -178.5357838
  lng : 123.82919969999999

Data comes from ISOBlue Public Data (11052016_ault_wheat_full.zip). But it seems I have wrong prescription about byte layout.

huseyinkozan commented 6 years ago

I didn't notice the offset at prescription. Here the right one:

      console.log("  lat :", (msg.data.readUInt32LE(0) * Number("1e-7")) - 210);
      console.log("  lng :", (msg.data.readUInt32LE(4) * Number("1e-7") - 210);

And output:

onMessage()
  data: <Buffer f2 99 95 95 1d d6 ce 49>
  lat : 40.96094579999999
  lng : -86.1708003

Here the help: https://groups.google.com/d/msg/isoblue/kERbzyyRr90/3xxo9zseCAAJ

sebi2k1 commented 6 years ago

I found the issue (see 73b9b8e81cbf138dcdd160d9b7200f36a05cc1b3).