Java (重新)连接设备失败,出现订阅异常
我正在使用azure iot设备SDK(1.3.31)连接模拟设备对于某些设备我在拨打此电话时遇到此异常:Java (重新)连接设备失败,出现订阅异常,java,azure,Java,Azure,我正在使用azure iot设备SDK(1.3.31)连接模拟设备对于某些设备我在拨打此电话时遇到此异常: //pseudo code deviceInfo.device = registryManager.getDevice(deviceId); String deviceConnectionString = new StringBuilder() .append("HostName=").append(hubHostname)
//pseudo code
deviceInfo.device = registryManager.getDevice(deviceId);
String deviceConnectionString = new StringBuilder()
.append("HostName=").append(hubHostname)
.append(";DeviceId=").append(device.getDeviceId())
.append(";SharedAccessKey=").append(device.getPrimaryKey())
.toString();
DeviceClient deviceClient = new DeviceClient(deviceConnectionString, IotHubClientProtocol.MQTT);
deviceClient.open();
还有一个例外:
java.io.IOException: Unable to subscribe to topic :devices/sim3_0001/messages/devicebound/# because java.io.EOFExceptionConnection lost
at com.microsoft.azure.sdk.iot.device.transport.mqtt.MqttIotHubConnection.open(MqttIotHubConnection.java:142) ~[iot-device-client-1.2.30.jar:na]
at com.microsoft.azure.sdk.iot.device.transport.mqtt.MqttTransport.open(MqttTransport.java:83) ~[iot-device-client-1.2.30.jar:na]
at com.microsoft.azure.sdk.iot.device.DeviceIO.open(DeviceIO.java:212) ~[iot-device-client-1.2.30.jar:na]
at com.microsoft.azure.sdk.iot.device.DeviceClient.open(DeviceClient.java:188) ~[iot-device-client-1.2.30.jar:na]
我对库代码做了一点挖掘,发现在订阅得到响应之前,我的连接已经断开了;这是已使用并转化为IOException的异常:
Connection lost (32109) - java.io.EOFException
at org.eclipse.paho.client.mqttv3.internal.CommsReceiver.run(CommsReceiver.java:146)
at java.lang.Thread.run(Thread.java:745)
Lost connection to the server. Reconnecting 0 time.
Caused by: java.io.EOFException
at java.io.DataInputStream.readByte(DataInputStream.java:267)
at org.eclipse.paho.client.mqttv3.internal.wire.MqttInputStream.readMqttWireMessage(MqttInputStream.java:65)
at org.eclipse.paho.client.mqttv3.internal.CommsReceiver.run(CommsReceiver.java:107)
此外,我还连接了iothub浏览器,查看是否获得了任何额外的有用信息。这就是它在我的公开电话中所说的:
body:
protocol: Mqtt
authType: { "scope": "device", "type": "sas", "issuer": "iothub" }
time: 2017-06-13T21:13:48.2406702Z
operationName: deviceConnect
category: Connections
level: Information
deviceId: sim3_0001
ipAddress: xx.xx.xxx.XXX
enqueuedTimeUtc: Tue Jun 13 2017 17:13:53 GMT-0400 (EDT)
offset: 355136
applicationProperties:
category: Connections
level: Information
operationName: deviceConnect
sequenceNumber: 705
annotations:
x-opt-sequence-number: 705
x-opt-offset: 355136
x-opt-enqueued-time: Tue Jun 13 2017 17:13:53 GMT-0400 (EDT)
offset: 355536
enqueuedTimeUtc: Tue Jun 13 2017 17:13:53 GMT-0400 (EDT)
body:
protocol: Mqtt
authType: { "scope": "device", "type": "sas", "issuer": "iothub" }
time: 2017-06-13T21:13:48.3656729Z
operationName: deviceDisconnect
category: Connections
level: Error
statusCode: 404
statusType: 404104
statusDescription: DeviceConnectionClosedRemotely
deviceId: sim3_0001
ipAddress: xx.xx.xxx.XXX
annotations:
x-opt-sequence-number: 706
x-opt-offset: 355536
x-opt-enqueued-time: Tue Jun 13 2017 17:13:53 GMT-0400 (EDT)
applicationProperties:
category: Connections
level: Error
operationName: deviceDisconnect
sequenceNumber: 706
另一个注意事项:新设备成功连接/订阅,似乎它们在重新连接时更经常失败。如果我将打开的调用放入循环中,并在睡眠1秒后重试,设备最终会成功连接。根据错误信息
java.io.IOException:无法订阅主题:devices/sim3_0001/messages/devicebound/#,因为java.io.eofeexception连接丢失
,我认为您试图通过订阅来接收云到设备的消息,使用devices/{device_id}/messages/devicebound/#
作为主题过滤器。Azure官方文档的小节将设备应用程序从AMQP迁移到MQTT
&接收云到设备消息
,已将问题原因解释如下
接收云到设备消息
要从物联网中心接收消息,设备应使用devices/{device_id}/messages/devicebound/#
作为主题过滤器进行订阅。主题筛选器中的多级通配符#仅用于允许设备接收主题名称中的其他属性。物联网中心不允许使用#或?通配符过滤子主题。由于IoT Hub不是一个通用的发布子消息代理,因此它只支持文档化的主题名称和主题过滤器
对于Azure IoT Hub,“MQTT不支持放弃/拒绝,因此我们将只显示从IoTHub收到的消息并返回完整信息”。GitHub上有一个官方文件,您可以参考它来更改代码并使其与MQTT一起工作。真正的答案是,针对MQTT协议的azure iot hub设备库只允许每个应用程序一个连接。该库仅创建一个MQTT连接,因此如果您创建第二个设备并尝试连接其中一个设备,则将强制断开连接 有趣的是,如果我将协议更改为IoTubClientProtocol.AMQPS,一切都会按预期进行。我没有显式订阅任何内容,我只是调用DeviceClient.open方法,该方法订阅azure设备库中的该主题。有趣的是,它偶尔会起作用;如果我使用10个不同的设备启动10个连接,打开的调用中的5个或6个将成功。如果您查看device/transport/mqtt/MqttMessaging.java,您将看到一旦建立了连接,它将立即订阅该主题:this.subscribeTopic=“devices/”+deviceId+“/messages/devicebound/#”;你能再看看这个吗?这仍然是我们的问题!