[英]TCP support in Azure IoT Hub
Azure IoT 中心支持 AMQP、MQTT、HTTP 協議。 為了自定義這些協議,我們有 Azure IoT 協議網關。 我可以找到關於 MQTT 協議定制的好樣本。 我需要一些使用 Azure IoT 協議網關進行基於 TCP 的協議自定義的示例代碼。
編輯(為了得到答案): OP 所問的是使用 Azure 協議網關來支持基於 TCP 的專有協議的示例。 目前物聯網中心僅支持 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 存儲庫中的這一行中實現。
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 網關現在被稱為 Azure IoT Edge,這在下面的 Azure github repo 中有明確提到
https://github.com/Azure/iot-edge-modbus.git
另一方面,Azure IoT Edge 支持某些協議的 TCP,可在以下鏈接中找到
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.