简体   繁体   English

Azure IoT 中心中的 TCP 支持

[英]TCP support in Azure IoT Hub

Azure IoT Hub Supports AMQP, MQTT, HTTP protocols. Azure IoT 中心支持 AMQP、MQTT、HTTP 协议。 In order to customize these protocols we have Azure IoT protocol gateway.为了自定义这些协议,我们有 Azure IoT 协议网关。 I can find good samples on MQTT protocol customization.我可以找到关于 MQTT 协议定制的好样本。 I need some sample codes for TCP based protocol customization using Azure IoT Protocol Gateway.我需要一些使用 Azure IoT 协议网关进行基于 TCP 的协议自定义的示例代码。

EDIT (in order to get an answer): what the OP was asking, is an example using the Azure Protocol Gateway to support a proprietary TCP-based protocol .编辑(为了得到答案): OP 所问的是使用 Azure 协议网关来支持基于 TCP 的专有协议的示例 Currently the IoT hub only supports AMQP, MQTT and HTTP.目前物联网中心仅支持 AMQP、MQTT 和 HTTP。 While those protocols actually rely on TCP, the hub doesn't support direct TCP connection without the extra layer of AMQP, MQTT or HTTP.虽然这些协议实际上依赖于 TCP,但如果没有额外的 AMQP、MQTT 或 HTTP 层,集线器不支持直接 TCP 连接。 As explained here , we need a basic example of a custom TCP based protocol.正如 这里所解释的,我们需要一个基于自定义 TCP 协议的基本示例。

Imagine a basic device that can only send some proprietary payload through TCP on a given IP address/port: we need an example of a gateway customization that allows this device to send data to the hub.想象一个基本设备,它只能在给定的 IP 地址/端口上通过 TCP 发送一些专有负载:我们需要一个网关定制示例,允许该设备向集线器发送数据。

The current code of the protocol gateway is poorly designed, as it heavily relies on MQTT.协议网关的当前代码设计不佳,因为它严重依赖于 MQTT。

Adding some bounty too.也增加了一些赏金。

The default Protocol Gateway sample are indeed somewhat confusing because of all the MQTT code.由于所有 MQTT 代码,默认协议网关示例确实有些令人困惑。 The protocol gateway works by 'simulating' a IoTHub connection for each custom protocol device you connect to the gateway.协议网关的工作原理是为您连接到网关的每个自定义协议设备“模拟”一个 IoTHub 连接。

To do this translation from the TCP device to an IoTHub device you first need to have a connection to the IoTHub on behalf of the device.要完成从 TCP 设备到 IoTHub 设备的转换,您首先需要代表设备连接到 IoTHub。 This is the gateway part.这是网关部分。 Below is the core essentials for this IoTHubConnection.以下是此 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;
        }
    }
}

The deviceClientFactory callback method should be implemented as shown below and in this line in the ProtocolGateway repo in Github. deviceClientFactory 回调方法应按如下所示实现,并在 Github 的 ProtocolGateway 存储库中的这一行中实现。

deviceClientFactory = IotHubClient.PreparePoolFactory(
    "IotHubConnectionString",
    400,
    TimeSpan.FromMinutes(3),
    iotHubClientSettings,
    PooledByteBufferAllocator.Default,
    new ConfigurableMessageAddressConverter("TopicNameConversion"));

When a Tcp Device connects to the protocol, you should create an instance of this IoTHubConnection and send messages from the Device to the IoTHubConnection and vica versa.当 Tcp 设备连接到协议时,您应该创建此 IoTHubConnection 的实例并将消息从设备发送到 IoTHubConnection,反之亦然。 The code below shows a very simple version of how this should be done.下面的代码显示了如何完成此操作的非常简单的版本。

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);
}

I know I am late to this conversation.我知道这次谈话我迟到了。 However I have interesting add on or might be a solution for some.但是,我有一些有趣的补充,或者可能是某些人的解决方案。

Azure IoT Gateway is now known as Azure IoT Edge, this is clearly mentioned in the following Azure github repo Azure IoT 网关现在被称为 Azure IoT Edge,这在下面的 Azure github repo 中有明确提到

在此处输入图片说明

https://github.com/Azure/iot-edge-modbus.git https://github.com/Azure/iot-edge-modbus.git

On the other hand, Azure IoT Edge supports TCP for some protocols which can be found in the following links另一方面,Azure IoT Edge 支持某些协议的 TCP,可在以下链接中找到

  1. https://docs.microsoft.com/en-us/azure/iot-edge/deploy-modbus-gateway https://docs.microsoft.com/en-us/azure/iot-edge/deploy-modbus-gateway
  2. https://docs.microsoft.com/en-us/azure/iot-edge/iot-edge-as-gateway https://docs.microsoft.com/en-us/azure/iot-edge/iot-edge-as-gateway

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

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