2017-03-16 102 views
9

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

EDIT(为了得到一个答案):什么OP是问,是使用Azure的协议网关为支持专有基于TCP协议一个例子。目前,物联网集线器仅支持AMQP,MQTT和HTTP。虽然这些协议实际上依赖于TCP,但是如果没有额外的AMQP,MQTT或HTTP层,集线器不支持直接的TCP连接。 如解释here,我们需要一个基于自定义TCP协议的基本示例。

试想一下,可以在给定的IP地址/端口对通过TCP只发送一些专有有效载荷的基本设备:我们需要一个网关定制,允许该设备将数据发送到所述轮毂的一个例子。

协议网关的当前代码设计不当,因为它很大程度上依赖于MQTT。

也添加一些赏金。

+1

TCP是所有这些消息协议的底层通信协议。你想做什么?你想要实现什么协议?为什么不使用可用的协议之一? –

+0

此外,您已经找到Azure IoT网关和示例。 MQTT协议本身是作为使用网关框架的定制添加的 –

+1

我的设备仅支持TCP通信。它通过TCP将同步消息发送到静态IP和端口。我希望此设备在Azure IoT Hub中虚拟化。这里描述的东西。 https://github.com/Azure/azure-iot-protocol-gateway/issues/44 –

回答

0

默认协议网关样品确实是的,因为所有的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回调方法应被实现为以下所示和在此行中的ProtocolGateway回购在Github上:https://github.com/Azure/azure-iot-protocol-gateway/blob/45d5b6ef57dce0027eef467cf14ac1ab6e3a358a/host/ProtocolGateway.Host.Common/Bootstrapper.cs#L149

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