Shouqun / node-dbus

dbus module for node
MIT License
150 stars 70 forks source link

How to send a byte array as part of a method argument? #228

Closed benfrancis closed 2 years ago

benfrancis commented 3 years ago

Thanks for creating this library. I've successfully used it to connect to an existing Wi-Fi access point via NetworkManager, but I'm struggling to figure out how to create a Wi-Fi access point.

Creating an access point via the AddAndActivateConnection method of NetworkManager requires constructing a complex variant which includes an SSID as a byte array.

Everything I've tried results in NetworkManager returning an error indicating it didn't understand the 802-11-wireless section of the object I provided as an argument to the method (see https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/issues/663).

I can't figure out how to create this byte array in Node.js (which lacks the Blob() constructor used in client-side JavaScript) and pass it as part of the argument to the method. I've tried various approaches with Node.js Buffers, but nothing seems to work.

Below is the code I've written, with the SSID as a string, but as I understand it the SSID needs to be a byte array rather than a string. I have two questions:

  1. Am I calling the method correctly?
  2. How can I include the SSID as a byte array?
 createWifiAccessPoint: function(ssid) {
    return new Promise((resolve, reject) => {
      this.systemBus.getInterface('org.freedesktop.NetworkManager',
        '/org/freedesktop/NetworkManager',
        'org.freedesktop.NetworkManager',
        (error, interface) => {

        if (error) {
          reject(error);
        }

        // Access point connection information
        let connectionInfo = {
          '802-11-wireless': {
            'ssid': ssid,
            'mode': 'ap'
          },
          'connection': {
            'id': ssid,
            'autoconnect': false,
            'type': '802-11-wireless',
          },
          'ipv4': {
            'method': 'manual',
            'address-data': {
              'address': '192.168.2.1',
              'prefix': 24,
            }
          }
        };

        interface.AddAndActivateConnection(connectionInfo, this.wifiAdapter, '/',
          function(error, value) {
          if (error) {
            console.error(error);
            reject(error);
          }
          resolve(value);
        });

      });
    });
    });
  },
richguernsey commented 3 years ago

When you used Buffer, did you pass the data property of the Buffer or the entire object?

benfrancis commented 3 years ago

@richguernsey I'm not exactly sure what you mean, sorry.

I've tried various approaches, but for example...

let ssidBuffer = Buffer.from(ssid);

then setting

'ssid': ssidBuffer,

in the object literal rather than

'ssid': ssid,

This doesn't feel right but I don't know how else to do it.

richguernsey commented 3 years ago

let connectionInfo = { '802-11-wireless': { 'ssid': Buffer.from(ssid, 'utf-8'), 'mode': 'ap' },

benfrancis commented 3 years ago

@richguernsey I just tried that and I think it's equivalent to what I wrote above because Buffer.from() defaults to utf-8. I still get the same error from dbus, which apparently means NetworkManager didn't recognise the 802-11-wireless section of my method argument:

A 'wireless' setting is required if no AP path was given.

This is why I'm guessing the SSID isn't being properly sent as an "ay" parameter, unless there's something else wrong with the configuration I'm passing?

benfrancis commented 3 years ago

@Shouqun I'm sorry to bother you, but this issue is blocking my project and I need to decide whether I need to switch to another library and re-write all the code I've written so far. Could you confirm whether there's support implemented for byte arrays in node-dbus? Thank you.

benfrancis commented 2 years ago

I finally found out how to convert a string into the byte array format expected over dbus by NetworkManager:

let ssid = 'my-ap';
let ssidByteArray = [];
let buffer = Buffer.from(ssid);
for (var i = 0; i < buffer.length; i++) {
  ssidByteArray.push(buffer[i]);
}

Fully working demonstrator here https://github.com/benfrancis/wifi-ap-producer/blob/master/index.js