Azure IoT Hub支持AMQP,MQTT,HTTP协议。为了定制这些协议,我们有Azure IoT协议网关。我可以在MQTT协议定制上找到很好的样本。我需要一些基于TCP的协议定制使用Azure IoT协议网关的示例代码。
编辑(为了得到答案):OP所问的是一个使用Azure Protocol Gateway来支持专有的基于TCP的协议的例子。目前IoT hub只支持AMQP,MQTT和HTTP。虽然这些协议实际上依赖于TCP,但是集线器不支持没有额外的AMQP,MQTT或HTTP层的直接TCP连接。正如这里所解释的,我们需要一个基于自定义TCP协议的基本示例。
设想一个基本设备,它只能在给定的IP地址/端口上通过TCP发送一些专有有效载荷:我们需要一个网关定制的示例,它允许这个设备向集线器发送数据。
当前的协议网关代码设计得很差,因为它严重依赖于MQTT。
还加了点赏金。
默认协议网关示例确实有些混乱,因为所有的MQTT代码。协议网关通过为连接到网关的每个自定义协议设备“模拟”一个IoTHub连接来工作。
要进行从TCP设备到IoTHub设备的转换,首先需要有一个代表设备到IoTHub的连接。这是网关部分。下面是这个IOThubConnection的核心要点。
namespace GatewayTest
{
using System;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using DotNetty.Buffers;
using Microsoft.Azure.Devices.ProtocolGateway.Identity;
using Microsoft.Azure.Devices.ProtocolGateway.IotHubClient;
using Microsoft.Azure.Devices.ProtocolGateway.Messaging;
public class IoTHubConnection : IMessagingChannel<IMessage>
{
private readonly string iotHubHostName;
private readonly Func<IDeviceIdentity, Task<IMessagingServiceClient>> deviceClientFactory;
private readonly Func<string, Task> onMessage;
private IMessagingServiceClient deviceClient;
private IDeviceIdentity deviceIdentity;
public IoTHubConnection(
string iotHubHostName,
Func<IDeviceIdentity, Task<IMessagingServiceClient>> deviceClientFactory,
Func<string, Task> onMessage)
{
this.iotHubHostName = iotHubHostName;
this.deviceClientFactory = deviceClientFactory;
this.onMessage = onMessage;
}
public event EventHandler CapabilitiesChanged;
public async Task OpenAsync(string deviceId, string deviceKey)
{
this.deviceIdentity = this.GetDeviceIdentity(deviceId, deviceKey);
if (this.deviceIdentity != UnauthenticatedDeviceIdentity.Instance)
{
this.deviceClient = await this.deviceClientFactory(this.deviceIdentity);
this.deviceClient.BindMessagingChannel(this);
}
}
public async Task CloseAsync()
{
await this.deviceClient.DisposeAsync(null);
this.deviceClient = null;
}
public void Handle(IMessage message)
{
var messageBody = message.Payload.ToString(Encoding.UTF8);
this.onMessage(messageBody);
this.deviceClient.CompleteAsync(message.Id);
}
public Task SendMessage(string message)
{
var buffer = Unpooled.WrappedBuffer(Encoding.UTF8.GetBytes(message));
var deviceMessage = this.deviceClient.CreateMessage($"devices/{this.deviceIdentity.Id}/messages/events", buffer);
return this.deviceClient.SendAsync(deviceMessage);
}
protected virtual void OnCapabilitiesChanged(EventArgs e)
{
this.CapabilitiesChanged?.Invoke(this, e);
}
private IDeviceIdentity GetDeviceIdentity(string userName, string deviceKey)
{
IotHubDeviceIdentity ideviceIdentity;
if (!IotHubDeviceIdentity.TryParse($"{this.iotHubHostName}/{userName}", out ideviceIdentity))
{
return UnauthenticatedDeviceIdentity.Instance;
}
ideviceIdentity.WithDeviceKey(deviceKey);
return ideviceIdentity;
}
}
}
deviceClientFactory回调方法应该如下所示,在GitHub中ProtocolGateway repo中的这一行中实现。
deviceClientFactory = IotHubClient.PreparePoolFactory(
"IotHubConnectionString",
400,
TimeSpan.FromMinutes(3),
iotHubClientSettings,
PooledByteBufferAllocator.Default,
new ConfigurableMessageAddressConverter("TopicNameConversion"));
当Tcp设备连接到协议时,您应该创建此IoTHubConnection的实例,并将消息从设备发送到IoTHubConnection,反之亦然。下面的代码显示了一个非常简单的版本。
private const int BufferSize = 1024;
private byte[] buffer = new byte[BufferSize];
private IoTHubConnection ioTHubConnection;
private NetworkStream stream;
private async Task Start()
{
listener = new TcpListener(IPAddress.Any, port);
listener.Start();
var client = await listener.AcceptTcpClientAsync();
ioTHubConnection = new IoTHubConnection("IoTHubName", deviceClientFactory, OnIoTHubMessage);
stream = client.GetStream();
// Read DeviceId and DeviceKey from some sort of StartConnection-message send by the TcpClient.
await ioTHubConnection.OpenAsync("DeviceId", "DeviceKey");
stream.BeginRead(buffer, 0, BufferSize, ReadTcpStreamCallback, null);
}
private void ReadTcpStreamCallback(IAsyncResult ar)
{
var bytesRead = stream.EndRead(ar);
if (bytesRead > 0)
{
var message = System.Text.Encoding.ASCII.GetString(result);
ioTHubConnection.SendMessage(message);
// Read again.
stream.BeginRead(buffer, 0, BufferSize, ReadTcpStreamCallback, null);
}
}
private async Task OnIoTHubMessage(string message)
{
// Potentially do some translation on the IoTHub message
// and send it to the Device
var byteData = Encoding.UTF8.GetBytes(message);
stream.BeginWrite(byteData, 0, byteData.Length, SendTcpCallback, null);
}
private void SendTcpCallback(IAsyncResult ar)
{
stream.EndWrite(ar);
}
我知道这次谈话我迟到了。然而,我有有趣的补充或可能是一个解决方案的一些。
Azure IoT Gateway现在被称为Azure IoT Edge,这在下面的Azure github回购中有明确提及
https://github.com/azure/iot-edge-modbus.git
另一方面,Azure IoT Edge支持TCP的某些协议,这些协议可以在以下链路中找到