当我发布或接收消息时,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 客户端与设备通信没有任何问题(我制作了一种服务器来将设备的信息同步到数据库)。现在我正在制作 Web 界面,所以我向我的 mosquitto.conf
添加了一个 WebSockets 侦听器,并使用 Paho MQTT 库编写了一个脚本 Javascript 来连接它,订阅主题 sgdrf/out
, 向主题 sgdrf/in
发送一条简单的 JSON 消息以获取在线设备列表,并在到达后处理 Python 服务器的响应。
问题及尝试的解决方案:我运行Django服务器,加载网页打开JS控制台发现MQTT客户端成功连接到broker但当它试图将消息发布到主题 sgdrf/in
时立即断开连接。这是控制台输出的每一行及其解释:
- onSuccess函数产生的消息,表明客户端成功连接到Mosquitto broker:
Conexión exitosa al broker MQTT.
- 在 onConnected 函数中,我添加了
console.log(uri)
以查看客户端连接到代理所使用的 URI。我有:
ws://localhost:61613/
- 在向控制台打印
uri
之后,我让客户端订阅 sgdrf/out
然后向控制台打印 'subscribed' :
subscribed
- 然后我调用
get_online_devices(mqtt_client)
,一个创建简单 JSON 字符串并将其发布到主题 sgdrf/in
的函数。但首先,它将字符串打印到控制台,以便我可以检查它(以防万一):
{"operator":"GetOnlineDevices","messageId":96792535859850080000,"info":{}}
- 然后,当
publish
方法真正执行时,是我得到这个错误的时候(由onConnectionLost函数捕获):
Pérdida de conexión con el broker MQTT: AMQJS0005E Internal error. Error Message: message is not defined, Stack trace: No Error Stack Available (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 侦听器,两者都不允许匿名连接,并使用密码文件进行身份验证。正如我之前所说,我启用和禁用匿名连接,并将端口号更改为 9001 并更改回 61613,我仍然有同样的错误。
结论:我不知道该做什么,这个项目的截止日期是下周。
我觉得有点傻,因为这真的是一个微不足道的打字错误。问题是 onMessageDelivered 和 onMessageArrived 函数有 msg
作为参数,但出于某种原因我在函数体中写了 message
。这就是“消息未定义”错误的意思,message
字面上没有定义。无论如何,我修复了它,现在它可以毫无问题地发送和接收消息。
...
更详细的故事:重要的是我是如何想出来的。
我决定亲力亲为,打开 paho-mqtt.js
的非缩小版。我查找了“无效错误”并找到了错误常量的定义位置,以及它在 catch 块中使用的两个位置。在两个 catch 块中,我注意到有一个三元运算符检查是否 (error.hasOwnProperty("stack") == "undefined")
但 true 和 false 子句被颠倒了,这就是为什么我得到“没有错误堆栈可用”的原因。
所以我颠倒了子句,实际上我在控制台中得到了堆栈跟踪(也许我应该在可能的时候向 Paho 开发团队提交错误报告)。堆栈跟踪在顶部有我的 mqtt_client_on_message_delivered
函数,所以我再次阅读它,突然间一切都变得有意义了。然后觉得浪费一个下午在这上面很蠢
前面的底线: Paho MQTT 客户端成功连接到我的 Mosquitto 代理,但在我尝试发布消息或从主题接收消息时立即断开连接它已订阅。我试过更改 Mosquitto 的监听端口和身份验证设置,并使用两个不同版本的 Paho MQTT,我仍然遇到同样的问题。
现在让我们进入细节。
简介: 我正在为一些通过 MQTT 通信的面部识别设备制作仪表板。我设置了一个 Mosquitto 代理,连接到它并使用 Python 的 Paho MQTT 客户端与设备通信没有任何问题(我制作了一种服务器来将设备的信息同步到数据库)。现在我正在制作 Web 界面,所以我向我的 mosquitto.conf
添加了一个 WebSockets 侦听器,并使用 Paho MQTT 库编写了一个脚本 Javascript 来连接它,订阅主题 sgdrf/out
, 向主题 sgdrf/in
发送一条简单的 JSON 消息以获取在线设备列表,并在到达后处理 Python 服务器的响应。
问题及尝试的解决方案:我运行Django服务器,加载网页打开JS控制台发现MQTT客户端成功连接到broker但当它试图将消息发布到主题 sgdrf/in
时立即断开连接。这是控制台输出的每一行及其解释:
- onSuccess函数产生的消息,表明客户端成功连接到Mosquitto broker:
Conexión exitosa al broker MQTT.
- 在 onConnected 函数中,我添加了
console.log(uri)
以查看客户端连接到代理所使用的 URI。我有:ws://localhost:61613/
- 在向控制台打印
uri
之后,我让客户端订阅sgdrf/out
然后向控制台打印 'subscribed' :subscribed
- 然后我调用
get_online_devices(mqtt_client)
,一个创建简单 JSON 字符串并将其发布到主题sgdrf/in
的函数。但首先,它将字符串打印到控制台,以便我可以检查它(以防万一):{"operator":"GetOnlineDevices","messageId":96792535859850080000,"info":{}}
- 然后,当
publish
方法真正执行时,是我得到这个错误的时候(由onConnectionLost函数捕获):Pérdida de conexión con el broker MQTT: AMQJS0005E Internal error. Error Message: message is not defined, Stack trace: No Error Stack Available (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 侦听器,两者都不允许匿名连接,并使用密码文件进行身份验证。正如我之前所说,我启用和禁用匿名连接,并将端口号更改为 9001 并更改回 61613,我仍然有同样的错误。
结论:我不知道该做什么,这个项目的截止日期是下周。
我觉得有点傻,因为这真的是一个微不足道的打字错误。问题是 onMessageDelivered 和 onMessageArrived 函数有 msg
作为参数,但出于某种原因我在函数体中写了 message
。这就是“消息未定义”错误的意思,message
字面上没有定义。无论如何,我修复了它,现在它可以毫无问题地发送和接收消息。
...
更详细的故事:重要的是我是如何想出来的。
我决定亲力亲为,打开 paho-mqtt.js
的非缩小版。我查找了“无效错误”并找到了错误常量的定义位置,以及它在 catch 块中使用的两个位置。在两个 catch 块中,我注意到有一个三元运算符检查是否 (error.hasOwnProperty("stack") == "undefined")
但 true 和 false 子句被颠倒了,这就是为什么我得到“没有错误堆栈可用”的原因。
所以我颠倒了子句,实际上我在控制台中得到了堆栈跟踪(也许我应该在可能的时候向 Paho 开发团队提交错误报告)。堆栈跟踪在顶部有我的 mqtt_client_on_message_delivered
函数,所以我再次阅读它,突然间一切都变得有意义了。然后觉得浪费一个下午在这上面很蠢