繁体   English   中英

当我发布或接收消息时,Paho MQTT JS 客户端失去与 Mosquitto 代理的连接(错误 AMQJS0005E)

[英]Paho MQTT JS client loses connection to Mosquitto broker when I publish or receive message (error AMQJS0005E)

前面的底线: Paho MQTT 客户端成功连接到我的 Mosquitto 代理,但当我尝试发布消息或收到来自它订阅的主题的消息时立即断开连接。 我尝试过更改 Mosquitto 的侦听端口和身份验证设置,并使用两个不同版本的 Paho MQTT,但我仍然遇到同样的问题。

现在让我们详细介绍一下。

简介:我正在为一些通过 MQTT 通信的面部识别设备制作仪表板。 我设置了一个 Mosquitto 代理,连接到它并使用 Python 的 Paho MQTT 客户端与设备通信没有问题(我制作了一种服务器来将设备的信息同步到数据库)。 Now I'm making the web interface, so I added a WebSockets listener to my mosquitto.conf and wrote a script using the Paho MQTT library for Javascript to connect to it, subscribe to topic sgdrf/out , send a simple JSON message to topic sgdrf/in获取在线设备列表,并处理Python服务器到达后的响应。

问题及尝试解决方法:我运行Django服务器,加载web页面,打开JS控制台发现MQTT客户端成功连接到broker,但是当它试图将消息发布到主题sgdrf/in时立即断开连接。 这是控制台 output 的每一行及其解释:

  1. onSuccess function 产生的消息,表示客户端成功连接到 Mosquitto 代理:

    Conexión exitosa al 代理 MQTT。

  2. 在onConnected function中,我添加了console.log(uri)来查看客户端连接broker使用的URI。 我有:

    ws://localhost:61613/

  3. uri打印到控制台后,我让客户端订阅sgdrf/out ,然后将“订阅”打印到控制台:

    订阅

  4. 然后我调用get_online_devices(mqtt_client) ,一个 function ,它创建一个简单的 JSON 字符串并将其发布到主题sgdrf/in 但首先,它将字符串打印到控制台,以便我可以检查它(以防万一):

    {"operator":"GetOnlineDevices","messageId":96792535859850080000,"info":{}}

  5. 然后,当实际执行publish方法时,是我收到此错误(由 onConnectionLost 函数捕获):

    Pérdida de conexión con el broker MQTT: AMQJS0005E 内部错误。 错误消息:消息未定义,堆栈跟踪:没有可用的错误堆栈(código:5)

我检查了 Mosquitto 日志文件,它只说何时连接了新客户端,然后由于套接字错误而断开连接(每次重新加载页面时)。 /var/log/mosquitto/mosquitto.log的尾部:

1614796149: New connection from 127.0.0.1 on port 61612.
1614796149: New client connected from 127.0.0.1 as mqttx_53195902 (p2, c1, k60, u'admin').
1614796182: Socket error on client sgdrf_dashboard_8499, disconnecting.
1614796325: New client connected from ::ffff:127.0.0.1 as sgdrf_dashboard_1597 (p2, c1, k60, u'admin').
1614796325: Socket error on client sgdrf_dashboard_1597, disconnecting.
1614796336: New client connected from ::ffff:127.0.0.1 as sgdrf_dashboard_6565 (p2, c1, k60, u'admin').
1614796336: Socket error on client sgdrf_dashboard_6565, disconnecting.
1614796931: New client connected from ::ffff:127.0.0.1 as sgdrf_dashboard_9773 (p2, c1, k60, u'admin').
1614796931: Socket error on client sgdrf_dashboard_9773, disconnecting.
1614797168: Saving in-memory database to /var/lib/mosquitto/mosquitto.db.

我尝试更改mosquitto.conf中的侦听端口,并启用和禁用身份验证,但它没有任何改变。 显然,每次更改配置文件时,我都必须重新启动 Mosquito。 我不认为问题出在蚊子身上。

无论我使用 Paho MQTT 1.1.0 版还是 1.0.3 版,我都有同样的问题。

作为一个实验,我在我的 Javascript 中注释掉了对get_online_devices的调用,这样它就不会尝试发布任何内容,重新加载页面并且没有错误,正如预期的那样。 然后,我使用 MQTTX 向 MQTT JS 客户端订阅的sgdrf/out主题发送了一条 JSON 消息,它立即断开连接并显示相同的错误消息。

代码:在页面底部( index.html )我有如下代码(原代码有Django模板标签填写一些值,所以这是浏览器收到的实际代码):

<!-- Paho MQTT -->
<script src="/static/js/paho-mqtt-min.js"></script>

<!-- Scripts -->
<script src="/static/js/dashboard.js"></script>
    
<script>
function get_online_devices(mqtt_client) {
    cmd = {
        operator: "GetOnlineDevices",
        messageId: generate_random_number_n_exp(20),
        info: {}
    };

    payload_string = JSON.stringify(cmd);
    console.log(payload_string)

    mqtt_client.publish("sgdrf/in", payload_string);
}

function add_device_to_list(device) {
    // Omitted for brevity. It's not being used yet.
}

let mqtt_client = make_mqtt_client("localhost", 61613);
let connection_options = make_connection_options(
    "admin",
    "CENSORED_PASSWORD"
);

mqtt_client.onConnected = function(reconnect, uri) {
    console.log(uri)
    mqtt_client.subscribe("sgdrf/out");
    console.log('subscribed');
    get_online_devices(mqtt_client);
};
mqtt_client.onConnectionLost = mqtt_client_on_connection_lost;
mqtt_client.onMessageDelivered = mqtt_client_on_message_delivered;

mqtt_client.onMessageArrived = function (msg) {
    // Omitted for brevity. Checks if the payload is a
    // JSON object with the right data and calls
    // add_device_to_list for each item of a list in it.
};

$(document).ready(function() {
    mqtt_client.connect(connection_options);

    $("#reload-device-list-btn").click(function() {
        get_online_devices(mqtt_client);
    });
});
</script>

上面提到的dashboard.js文件只是有一些我认为对其他页面有用的功能,所以我将它们分开到一个文件中:

// dashboard.js
function generate_random_number_n_exp(n) {
    return parseInt(Math.random() * Math.pow(10, n), 10)
}

function make_mqtt_client(host, port) {
    let client_id = "sgdrf_dashboard_" + generate_random_number_n_exp(4);
    return new Paho.Client(host, port, '/', client_id);
}

function make_connection_options(user, password) {
    let connection_options = {
        userName: user,
        password: password,
        onSuccess: mqtt_client_on_success,
        onFailure: mqtt_client_on_failure,
    };
    
    return connection_options;
}

function mqtt_client_on_success() {
    console.log('Conexión exitosa al broker MQTT.');
}

function mqtt_client_on_failure(error) {
    console.log(
        'Fallo de conexión con el broker MQTT: ' + error.errorMessage
        + ' (código: ' + error.errorCode + ')'
    );
}

function mqtt_client_on_connection_lost (error) {
    console.log('Pérdida de conexión con el broker MQTT: ' + error.errorMessage
        + ' (código: ' + error.errorCode + ')'
    );
}

function mqtt_client_on_message_delivered(msg) {
    let topic = message.destinationName;
    let payload = message.payloadString;
    console.log("Mensaje enviado a " + topic + ": " + payload);
}

function mqtt_client_on_message_arrived(msg) {
    let topic = message.destinationName;
    let payload = message.payloadString;
    console.log("Mensaje recibido de " + topic + ": " + payload);
}

这是我的mosquitto.conf文件的内容:

per_listener_settings true
listener 61612
allow_anonymous false
password_file /home/s8a/Projects/sgdrf/config/pwdfile.txt

listener 61613
protocol websockets
allow_anonymous false
password_file /home/s8a/Projects/sgdrf/config/pwdfile.txt

它只是设置了一个 TCP 监听器和一个 WebSockets 监听器,都不允许匿名连接,并使用 pwdfile 进行身份验证。 正如我之前所说,我启用和禁用了匿名连接,并将端口号更改为 9001 并恢复为 61613,我仍然有同样的错误。

结论:我不知道该怎么办,这个项目的截止日期是下周。

我觉得有点愚蠢,因为这确实是一个微不足道的打字错误。 问题是 onMessageDelivered 和 onMessageArrived 函数有msg作为参数,但我出于某种原因在 function 正文中写了message 这就是“消息未定义”错误的含义, message实际上未定义。 无论如何,我修复了这个问题,现在它可以毫无问题地发送和接收消息。

...

更详细的故事:重要的是我是如何想出来的。

我决定亲自动手并打开paho-mqtt.js的非缩小版本。 我查找“无效错误”并找到错误常量的定义位置,以及在 catch 块中使用它的两个位置。 在两个 catch 块中,我注意到有一个三元运算符检查 if (error.hasOwnProperty("stack") == "undefined")但是真假子句被颠倒了,这就是为什么我得到“没有可用的错误堆栈” .

所以我颠倒了这些条款,确实我在控制台中得到了一个堆栈跟踪(也许我应该尽可能地向 Paho 开发团队提交一份错误报告)。 堆栈跟踪的顶部有我的mqtt_client_on_message_delivered function,所以我再次阅读它,突然一切都变得有意义了。 然后我觉得浪费了一个下午在这件事上很愚蠢。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM