Arduino-iot-js NPM Package Throws at Runtime

I am desperately trying to interact with the Arduino IoT Cloud via a Web App from a Browser, and am defeated at every turn. I have another thread in the forums about CORS violations trying to access the REST API Client, and now I'm trying to use arduino-iot-js to receive and set Thing Property values in real time via an MQTT channel, and it fails at runtime.

It throws this error very early (before even calling any functions from the library) when it's imported and referenced, per the Chrome Dev Console:

constants.js:46 Uncaught ReferenceError: Buffer is not defined
    at node_modules/mqtt-packet/constants.js (constants.js:46:34)
    at __require (chunk-IEMOZLTW.js?v=27d7d660:40:50)
    at node_modules/mqtt-packet/parser.js (parser.js:4:19)
    at __require (chunk-IEMOZLTW.js?v=27d7d660:40:50)
    at node_modules/mqtt-packet/mqtt.js (mqtt.js:1:18)
    at __require (chunk-IEMOZLTW.js?v=27d7d660:40:50)
    at node_modules/mqtt/lib/client.js (client.js:10:20)
    at __require (chunk-IEMOZLTW.js?v=27d7d660:40:50)
    at node_modules/mqtt/lib/connect/index.js (index.js:3:20)
    at __require (chunk-IEMOZLTW.js?v=27d7d660:40:50)

The error is in this line:
protocol.SESSIONPRESENT_HEADER = Buffer.from([protocol.SESSIONPRESENT_MASK])
(Line 46 of node_modules/mqtt-packet/consstants.js)

Note that this doesn't appear to crash on any particular usage off the package. Simply importing the package and having a reference to to it, like "...await ArduinoIoTCloud.connect(...", causes the crash on startup. The call to "ArduinoIoTCloud.connect" never gets executed; the app doesn't get anywhere near that far before the exception. Just having the reference in the code, causing the package to be included, causes the crash at startup.

I've done an "npm update" to ensure the latest package versions, and the problem persists.

Any idea what's up here, and how to fix it?
 

ADDITIONAL INFO:

  • This problem only appears to happen in the Browser. It does not occur in a Node app.
  • Even though the crash doesn't happen in a Node app, the Node app exhibits these issues:
    • "client.sendProperty(thingId, name, value);" isn't able to set Booleans to false.
    • It can set Numbers to anything, and it can set Booleans to true, but it can not set Booleans to false. A True value remains True even after "sendProperty...." with 'false'. I've tried "false", false, and 0 - nothing works.
    • Changes to Property values (via the Web Dashboard or via a Node app) are not being transmitted to the client, per this setup:
  client.onPropertyValue(thingId, name, (value) => {
            console.log(`RECEIVED ${name} value ${value}`);
        });
   -- Am I setting up that callback wrong?

While the overlap between client-side and server-side JavaScript is high, it is not 100%. As the error message says, the browser does not have Buffer. When in doubt, compare search results for "mdn whatever" and "node whatever". Docs for the standard library for Deno, a Node successor, mention for its own server-side implementation

Node's Buffer was created in 2009 before JavaScript had the concept of ArrayBuffers. It's simply a non-standard ArrayBuffer.

ArrayBuffer was my top search result for "mdn Buffer"; that and its relatives are what you use in a browser. Node's own docs for Buffer used to say

Prior to the introduction of TypedArray, the JavaScript language had no mechanism for reading or manipulating streams of binary data. The Buffer class was introduced as part of the Node.js API to enable interaction with octet streams in TCP streams, file system operations, and other contexts.

With TypedArray now available, the Buffer class implements the Uint8Array API in a manner that is more optimized and suitable for Node.js.

Note that the last release version, the 4-1/2-year-old 0.4.7, does not use Buffer. But just last week the version was bumped on the master branch from 0.12.0 to 0.13.0. At some point, the first sentence of the README, that the library

can be used both from the browser and Node.js

became also not 100%. I have not used the library, but I'm guessing at some point the usage diverged. Maybe you can achieve what you want, but not the way you're doing it?

Finally, the docs for Node's Buffer where changed a while back to say

The Buffer class is a subclass of JavaScript's Uint8Array class and extends it with methods that cover additional use cases. Node.js APIs accept plain Uint8Arrays wherever Buffers are supported as well.

So maybe there's a way to update the library so that more parts can run in a browser. Not something I would attempt without knowing the whole picture.

Thanks for the investigation and information.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.