首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Azure IoT集线器中的TCP支持

Azure IoT集线器中的TCP支持
EN

Stack Overflow用户
提问于 2017-03-16 16:28:32
回答 2查看 3.9K关注 0票数 15

Azure IoT集线器支持AMQP、MQTT、HTTP协议。为了定制这些协议,我们有Azure IoT协议网关。我可以在MQTT协议定制上找到很好的示例。我需要一些使用Azure IoT协议网关的基于TCP的协议定制的示例代码。

编辑(为了得到答案):OP要求的是一个使用Azure协议网关来支持基于TCP的专有协议的示例。目前,IoT集线器只支持AMQP、MQTT和HTTP。虽然这些协议实际上依赖于TCP,但在没有AMQP、MQTT或HTTP额外层的情况下,集线器不支持直接TCP连接。正如解释的那样,我们需要一个基于这里的自定义协议的基本示例。

假设一个基本设备只能在给定的IP地址/端口上通过TCP发送一些专有的有效负载:我们需要一个网关定制的示例,它允许该设备向集线器发送数据。

协议网关的当前代码设计很差,因为它严重依赖于MQTT。

也加了点赏金。

EN

回答 2

Stack Overflow用户

发布于 2018-02-07 19:41:22

由于所有的MQTT代码,默认的协议网关示例确实有些混乱。协议网关通过为连接到网关的每个自定义协议设备“模拟”一个IoTHub连接来工作。

要完成从TCP设备到IoTHub设备的转换,首先需要代表设备连接到IoTHub。这是网关部分。下面是这个IoTHubConnection的核心要点。

代码语言:javascript
运行
复制
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回调方法应该实现如下所示,并在这条线中的ProtocolGateway回购中实现。

代码语言:javascript
运行
复制
deviceClientFactory = IotHubClient.PreparePoolFactory(
    "IotHubConnectionString",
    400,
    TimeSpan.FromMinutes(3),
    iotHubClientSettings,
    PooledByteBufferAllocator.Default,
    new ConfigurableMessageAddressConverter("TopicNameConversion"));

当Tcp设备连接到协议时,您应该创建此IoTHubConnection的一个实例,并从该设备向IoTHubConnection发送消息,反之亦然。下面的代码展示了如何做到这一点的一个非常简单的版本。

代码语言:javascript
运行
复制
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);
}
票数 3
EN

Stack Overflow用户

发布于 2020-06-01 13:42:31

我知道我这次谈话迟到了。不过,我有一个有趣的补充,或可能是一个解决方案的一些。

Azure IoT网关现在被称为Azure IoT边缘,下面的Azure github回购清楚地提到了这一点

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

另一方面,Azure IoT边缘支持某些协议,这些协议可以在以下链接中找到

  1. https://learn.microsoft.com/en-us/azure/iot-edge/deploy-modbus-gateway
  2. https://learn.microsoft.com/en-us/azure/iot-edge/iot-edge-as-gateway
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42839683

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档