Search code examples
node.jsnetwork-programmingwiresharkcoap

How to register LwM2M client with node-coap package?


I'm trying to emulate LwM2M client nodes with node.js coap package. I have LwM2M server running and listening to port 5555 at my Raspberry Pi 3.

Currently all I've achieved is sending an UDP packet to lo (loopback) interface. (However it's encapsulated inside another UDP packet which has source and destination of 00:00:00:00:00:00, but that doesn't matter to me right now).

const coap  = require('../') // Script is located inside package examples directory

const endpointClientName = 'someSensor'
const lifetime = '600'
const version = '1.0'
const binding = 'UQ'
let bodyString = '?ep=' + endpointClientName + '&lt=' + lifetime + '&lwm2m=' + version + '&b=' + binding;
let responseBody = '';
let options = {
  host : 'fd72:cafe:face:0:fade:deaf:1234:5678',
  port : 5555,
  pathname : "/rd",
  method : 'POST',
  confirmable : 'true',
  options : {
    'Accept' : 'application/json'
  }
};
let request = coap.request(options);

request.on('response', function (response) {
  response.on('data', function () {
    responseBody += response.payload.toString();
  });
  response.on('end', function () {
    if (response.code == '2.01') {
      console.log('[coap] device registered.');
      var obj = JSON.parse(responseBody);
      console.log('[coap] responseBody', obj);
    } else {
      console.log('[coap] coap response.code=' + response.code);
    }
  });
});
request.write(bodyString);
request.end();

code above produces UDP packet which contains data:

Data (50 bytes)
    Data: 44021dff8ea487ebb272646132ff3f65703d736f6d655365...
    [Length: 50]

data below pasted from wireshark as hex dump

0000   44 02 1d ff 8e a4 87 eb b2 72 64 61 32 ff 3f 65
0010   70 3d 73 6f 6d 65 53 65 6e 73 6f 72 26 6c 74 3d
0020   36 30 30 26 6c 77 6d 32 6d 3d 31 2e 30 26 62 3d
0030   55 51

However I'm expecting Wireshark to show packet as CoAP packet, which would contain segments separated into several parts:

  1. Opt Name: #1: Uri-Path: rd
  2. Opt Name: #2: Uri-Query: ep=someSensor
  3. Opt Name: #3: Uri-Query: lt=600
  4. Opt Name: #4: Uri-Query: lwm2m=1.0
  5. Opt Name: #5: Uri-Query: b=UQ

What am I doing wrong? Perhaps I'm setting wrong options? I've noticed that some send request to address coap://localhost:port/path, however I've failed to achieve better results by using other ways.


Solution

  • The whole problem was that options like lifetime and lwm2m version were in packet body, however it has to be described in query:

    query: Query string. Defaults to ''. Should not include the path, e.g. 'a=b&c=d'

    also after registering device, response is not in json format, also all information is not in response body, but in response options:

    message.options

    All the CoAP options, as parsed by CoAP-packet.

    All the options are in binary format, except for 'Content-Format', 'Accept' and 'ETag'. See registerOption() to know how to register more.

    See the spec for all the possible options.

    With that said, problem is solved by slightly modifying the code:

    const coap  = require('../') // Script is located inside package examples directory
    
    const serverAddress = 'fd72:cafe:face:0:fade:deaf:1234:5678'
    const serverPort = 5555
    const endpointClientName = 'someSensor'
    const lifetime = '600'
    const version = '1.0'
    const binding = 'UQ'
    const uriQuery = 'ep=' + endpointClientName + '&lt=' + lifetime + '&lwm2m=' + version + '&b=' + binding;
    const clientResources = '/1/0'
    let options = {
      host : serverAddress,
      port : serverPort,
      pathname : "/rd",
      method : 'POST',
      confirmable : 'true',
      query : uriQuery,
    };
    let request = coap.request(options);
    
    request.on('response', function (response) {
      console.log('[coap] coap response.code = ' + response.code);
      console.log('[coap] coap response.options = ' + response.options);
    });
    request.write(clientResources);
    request.end();