2017-03-16 99 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); 
}