【问题标题】:Connect to Azure IotHub using MQTT in Javascript在 Javascript 中使用 MQTT 连接到 Azure IotHub
【发布时间】:2018-08-06 16:18:37
【问题描述】:

当我尝试使用MQTT.js (https://github.com/mqttjs/MQTT.js) 连接到 Azure IotHub 时,我不断回复 Connection refused: Not authorized

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

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

如何使用 3rd 方 MQTT 库和 SAS 令牌通过 Javascript 进行连接?

这是一段 Javascript 代码的 sn-p:

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)

【问题讨论】:

  • 为什么不使用IoT Hub Device SDK?第 3 方 MQTT 库在 Azure IoT Hub 中是一种偶然发现,因为它不是一个真正的 代理(至少它不应该那样使用)。
  • 刚刚试了一下,确实,它会抛出未经身份验证的 MQTTS,但可以在 Websockets 上运行,var client = MQTT.connect(`wss://${url}`,...
  • 不,说得太早了。挂在wss://
  • @evilSnobu 我需要使用 MQTT(没有 AMQP 或其他协议),并且我试图避免包含我不会使用的代码,例如IoT Hub SDK 包含我不需要的不同协议的代码。另外:普通 MQTT 是 IoT Hub 官方文档中的一个有效选项。
  • 不一定。你只能导入这个包:npmjs.com/package/azure-iot-device-mqtt。对于Message 类型,您可以从azure-iot-common lib 中借用代码。

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


【解决方案1】:

是的,Azure IoT Hub 支持 MQTT,您可以使用 MQTT 协议直接连接 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 Hub 中的 DEVICE ID 作为连接选项中的 clientId;
  2. 使用mqtts协议;
  3. 对于 username 选项,使用 {iothubhostname}/{device_id}/api-version=2016-11-14,其中 {iothubhostname} 是 IoT 中心的完整 CName。
  4. 对于 password 字段,使用 SAS 令牌。您可以使用 Device Explorer 获取 SAS 令牌。 SAS 令牌必须使用涉及以下权限的策略生成:“注册表写入”、“服务连接”和“设备连接”(少于这三个的组合可能有效,但提供“注册表写”是不够的)。

【讨论】:

  • 谢谢 :) 但这给了Error: Connection refused: Server unavailable
  • @TPPZ 为我工作。检查您的 SAS / 用户名。格式错误的用户名也会导致我的服务器不可用。
  • @Michael Xu 您使用的 SAS 令牌的结构是什么?键/值中定义了哪些字段?不适用于此 Javascript 示例的相同凭据,而是适用于使用 Paho 的 Python 代码和我从 github.com/Azure/azure-iot-sdk-c/blob/master/certs/certs.c 数组的第一个元素复制的数字证书(如官方文档中所示)跨度>
  • 好的,我使用具有不同权限的不同策略(用户名)来完成这项工作。似乎权限:必须提供“服务连接”和“设备连接”(一个或另一个或两者)。我正在尝试“注册表写入”(我认为包括“注册表读取”)许可,认为这就足够了。
  • 谢谢,这很好用。你能举个关于“订阅”的例子吗?我在async.mqtt 库中找不到订阅示例
【解决方案2】:

我遇到了同样的问题。尝试了半小时后,我才知道我的一位同事在 Iothub 上禁用了我的设备。?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    • 2022-06-19
    相关资源
    最近更新 更多