node.js - 在 Javascript 中使用 MQTT 连接到 Azure IotHub

标签 node.js azure mqtt azure-iot-hub sasl

尝试使用 MQTT.js 连接到 Azure IotHub 时,我不断返回连接被拒绝:未授权 ( https://github.com/mqttjs/MQTT.js )。

SAS 密码是使用 Microsoft Device Explorer ( https://github.com/Azure/azure-iot-sdk-csharp/tree/master/tools/DeviceExplorer ) 生成的,因此提供正确的读/写连接详细信息以及 future 的到期日期,我假设它是正确且有效的。

我还要求通过 rejectUnauthorized: false 启用 TLS/SSL(根据 Microsoft Azure 文档: https://learn.microsoft.com/en-us/azure/iot-hub/iot-hub-mqtt-support#tlsssl-configuration )(如 MQTT.js 文档 https://github.com/mqttjs/MQTT.js#client 中所述) .

如何使用第三方 MQTT 库和 SAS token 通过 Javascript 进行连接?

这是 Javascript 代码的片段:

var MQTT = require("async-mqtt");

const deviceId = "<PUT_SOMETHING_HERE>";
const iotHubName = "<PUT_SOMETHING_HERE>";

const url = `${iotHubName}.azure-devices.net/${deviceId}/api-version=2016-11-14`;
const iotHubTopic = `devices/${deviceId}/messages/events/`

var client = MQTT.connect(`mqtts://${url}:8883`, {
  username: url,
  password: `SharedAccessSignature sr=${iotHubName}.azure-devices.net&sig=<COMBINATION_OF_PASSWORDS_URL_ENCODED>&se=<EPOCH_EXPIRY>&skn=<ACCESS_POLICY_NAME>`,
  rejectUnauthorized: false, // https://github.com/mqttjs/MQTT.js#client
});

// this is code from the MQTT.js example, but I don't even reach it
async function doStuff() {

    console.log("Starting");
    try {
        await client.publish(iotHubTopic, "It works!");
        // This line doesn't run until the server responds to the publish
        await client.end();
        // This line doesn't run until the client has disconnected without error
        console.log("Done");
    } catch (e){
        // Do something about it!
        console.log("Error while sending a message...");
        console.log(e.stack);
        process.exit();
    }
}

const ceremony = () => {
  return new Promise((resolve, reject) => {
      client.on("connect", doStuff);
      return resolve();
    })
    .then((stuff) => {
      console.log("Done?", stuff);
    })
    .catch((err) => {
      console.log("Err...", err);
      process.exit();
    });
}

ceremony();

输出是这样的:

Done? undefined
events.js:183
      throw er; // Unhandled 'error' event
      ^

Error: Connection refused: Not authorized
    at MqttClient._handleConnack (<PATH_TO_THE_JS_PROJECT>/node_modules/mqtt/lib/client.js:896:15)
    at MqttClient._handlePacket (<PATH_TO_THE_JS_PROJECT>/node_modules/mqtt/lib/client.js:332:12)
    at work (<PATH_TO_THE_JS_PROJECT>/node_modules/mqtt/lib/client.js:274:12)
    at Writable.writable._write (<PATH_TO_THE_JS_PROJECT>/node_modules/mqtt/lib/client.js:284:5)
    at doWrite (<PATH_TO_THE_JS_PROJECT>/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:428:64)
    at writeOrBuffer (<PATH_TO_THE_JS_PROJECT>/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:417:5)
    at Writable.write (<PATH_TO_THE_JS_PROJECT>/node_modules/mqtt/node_modules/readable-stream/lib/_stream_writable.js:334:11)
    at TLSSocket.ondata (_stream_readable.js:639:20)
    at emitOne (events.js:116:13)
    at TLSSocket.emit (events.js:211:7)

最佳答案

是的,Azure IoT Hub支持MQTT,您可以使用MQTT协议(protocol)直接与IoT Hub连接,并使用记录的主题名称和主题过滤器以发送/接收消息的方式发布/订阅主题。我修改了上面的代码,效果很好。

var MQTT = require("async-mqtt");

const deviceId = "{the device name}";
const iotHubName = "{your iot hub name}";
const userName = `${iotHubName}.azure-devices.net/${deviceId}/api-version=2016-11-14`;
const iotHubTopic = `devices/${deviceId}/messages/events/`;

var client = MQTT.connect(`mqtts://${iotHubName}.azure-devices.net:8883`, {
  keepalive: 10,
  clientId: deviceId,
  protocolId: 'MQTT',
  clean: false,
  protocolVersion: 4,
  reconnectPeriod: 1000,
  connectTimeout: 30 * 1000,
  username: userName,
  password: "{SAS Token}",
  rejectUnauthorized: false, 
});

// this is code from the MQTT.js example, but I don't even reach it
async function doStuff() {

    console.log("Starting");
    try {
        await client.publish(iotHubTopic, "It works!");
        // This line doesn't run until the server responds to the publish
        await client.end();
        // This line doesn't run until the client has disconnected without error
        console.log("Done");
    } catch (e){
        // Do something about it!
        console.log("Error while sending a message...");
        console.log(e.stack);
        process.exit();
    }
}

const ceremony = () => {
  return new Promise((resolve, reject) => {
      client.on("connect", doStuff);
      return resolve();
    })
    .then((stuff) => {
      console.log("Done?", stuff);
    })
    .catch((err) => {
      console.log("Err...", err);
      process.exit();
    });
}

ceremony();

在代码中,需要注意的是:

  1. 使用 IoT 中心中的DEVICE ID作为连接选项中的 clientId;
  2. 使用mqtts协议(protocol);
  3. 对于用户名选项,请使用 {iothubhostname}/{device_id}/api-version=2016-11-14,其中 {iothubhostname} 是 IoT 中心的完整 CName。
  4. 对于密码字段,请使用 SAS token 。您可以使用Device Explorer获取 SAS token 。 SAS token 必须使用涉及以下权限的策略生成:“注册表写入”、“服务连接”和“设备连接”(少于这三者的组合可能有效,但提供“注册表” write” 肯定是不够的)。

请参阅此处了解更多详细信息:Using the MQTT protocol directly (as a device)

关于node.js - 在 Javascript 中使用 MQTT 连接到 Azure IotHub,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51711853/

相关文章:

mysql - 如何使用node执行mysql转储文件

node.js - 如何正确构造和使用套接字缓冲区?

node.js - 无法在nodejs中关闭串口

azure - 在 Azure 中,为什么 AuthClientId 也称为应用程序 Id?

azure - 应用服务 VNet 与 Azure 存储服务端点集成

c# - 使用 Blob 存储索引器的 Azure 搜索元数据中的 base64 路径无效

javascript - 编译后的 typescript 和 vanilla javascript 之间的内存使用情况不同

javascript - Node.js - 公开吗?

javascript - 如何使用 Websockets 连接到 MQTT Broker?

ssl - Mosquitto 与 MQTTS 和 WSS 在同一个代理中