通过 TMS MQTT 连接到 Azure IoTHub

问题描述 投票:0回答:1

我正在尝试通过 Delphi 中的 TMS MQTT 连接到 Azure IoTHub。每次都会出现“连接丢失”的情况。我尝试了两种方法:使用证书和连接字符串。

例如我的代码使用证书创建客户端:

FMQTTClient := TTMSMQTTClient.Create(nil);

FMQTTClient.BrokerHostName := Format('%s.azure-devices.net', \[FIoTHubHostName\]);
  FMQTTClient.BrokerPort := 443;  // also tried 8883, got "csConnectionRejected_ClientNotAuthorized"

FMQTTClient.ClientID := FMyDeviceId;

FMQTTClient.OnConnectedStatusChanged := OnConnectedStatusChanged;
  FMQTTClient.OnPublishReceived := OnMessageReceived;
  FMQTTClient.OnSSLIOHandlerConfiguration := OnSSLIOHandlerConfiguration;

FMQTTClient.KeepAliveSettings.AutoReconnect:= True;
  FMQTTClient.KeepAliveSettings.KeepAliveInterval := 30;
  FMQTTClient.KeepAliveSettings.KeepConnectionAlive := True;

FMQTTClient.Credentials.Username :=
    Format('%s.azure-devices.net/%s/?api-version=2020-09-30', \[FIoTHubHostName, FMyDeviceId\]);

// Password is not needed for client certificate authentication
  FMQTTClient.Credentials.Password := '';

if not IdSSLOpenSSLHeaders.Load then
    raise Exception.Create('Failed to load OpenSSL');
  if not IsOpenSSL_TLSv1_2_Available then
    raise Exception.Create('TLSv1_2 is not available');

FMQTTClient.UseSSL := True;

BYW,使用此证书在 Python 上编写的类似客户端可以工作,所以我认为这不是根本原因。

以及配置 SSL 连接的代码:

procedure TMQTTClient.OnSSLIOHandlerConfiguration(ASender: TObject;
  var ASSLIOHandler: TIdSSLIOHandlerSocketOpenSSL);
begin
  ASSLIOHandler.SSLOptions.CertFile := FCertFileName;    // Device certificate
  ASSLIOHandler.SSLOptions.KeyFile := FKeyFileName;      // Device private key
  ASSLIOHandler.SSLOptions.Mode := sslmClient;
  ASSLIOHandler.SSLOptions.Method := sslvTLSv1_2;
end;

但是每次我在这里得到“csConnectionLost”:

procedure TMQTTClient.OnConnectedStatusChanged(ASender: TObject;
  const AConnected: Boolean; AStatus: TTMSMQTTConnectionStatus);
var
  lConnStr: string;
begin
  if AConnected {and (AStatus = csConnected)} then
  begin
    ShowMessage('Connected: True');
    if FMQTTClient.Subscribe('$iothub/methods/POST/#') > 0 then
      ShowMessage('Subscribe: Ok')
    else
      ShowMessage('Subscribe: Error');
  end
  else
    if not AConnected then
    begin
      // The client is NOT connected and any interaction with the broker will result in an exception.
      case AStatus of
        csConnectionRejected_InvalidProtocolVersion: lConnStr := 'ConnectionRejected_InvalidProtocolVersion';
        csConnectionRejected_InvalidIdentifier     : lConnStr := 'ConnectionRejected_InvalidIdentifier';
        csConnectionRejected_ServerUnavailable     : lConnStr := 'ConnectionRejected_ServerUnavailable';
        csConnectionRejected_InvalidCredentials    : lConnStr := 'ConnectionRejected_InvalidCredentials';
        csConnectionRejected_ClientNotAuthorized   : lConnStr := 'ConnectionRejected_ClientNotAuthorized'; // the connection is rejected by broker
        csConnectionLost  : lConnStr := 'ConnectionLost'; // the connection with the broker is lost
        csConnecting      : lConnStr := 'Connecting';     // The client is trying to connect to the broker
        csReconnecting    : lConnStr := 'Reconnecting';   // The client is trying to reconnect to the broker
      else
        lConnStr := 'Unknown status:' + IntToStr(Integer(AStatus));
      end;
      ShowMessage('Status: ' + lConnStr);
    end;
end;

小伙伴们有什么想法吗?

请告诉我我在这里做错了什么。感谢任何帮助。

azure delphi mqtt
1个回答
0
投票

我按照此 MSDOC 使用 MQTT 通过共享访问签名与 Azure IoT 中心进行通信。

我还按照这个 GitHub 存储库Delphi 中使用 MQTT 客户端。

下面是通过 MQTT 连接到 Azure IoT Hub 并向设备发送指定消息的 Delphi 代码。

const
  IOT_HUB_NAME      = "{iothub_name}";
  IOT_HUB_DEVICE_ID = "{device_id}";
  IOT_HUB_SAS_TOKEN = SharedAccessSignature sr=...&sig=...&se=...';
  MQTT_BROKER       = IOT_HUB_NAME + '.azure-devices.net';
  MQTT_PORT         = 8883;

var
  MQTTClient: TMQTTClient;
  SSL: TIdSSLIOHandlerSocketOpenSSL;
  Messages: array[0..4] of string;
  I: Integer;
  PublishResult: Boolean;

procedure OnConnect(Sender: TObject);
begin
  WriteLn('Connected to IoT Hub');
end;

procedure OnDisconnect(Sender: TObject);
begin
  WriteLn('Disconnected from IoT Hub');
end;

procedure OnPublish(Sender: TObject; const Topic: string; const Payload: string);
begin
  WriteLn('Published to topic: ' + Topic + ' with payload: ' + Payload);
end;

begin
  try
    
    MQTTClient := TMQTTClient.Create(nil);
    try
      MQTTClient.OnConnect := OnConnect;
      MQTTClient.OnDisconnect := OnDisconnect;
      MQTTClient.OnPublish := OnPublish;

    
      SSL := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
      try
        SSL.SSLOptions.Method := sslvTLSv1_2; 
        SSL.SSLOptions.VerifyMode := [];
        MQTTClient.IOHandler := SSL;
        MQTTClient.Username := IOT_HUB_NAME + '.azure-devices.net/' + IOT_HUB_DEVICE_ID + '/?api-version=2021-04-12';
        MQTTClient.Password := IOT_HUB_SAS_TOKEN;

        MQTTClient.Connect(MQTT_BROKER, MQTT_PORT);

        Messages[0] := 'Accio';
        Messages[1] := 'Aguamenti';
        Messages[2] := 'Alarte Ascendare';
        Messages[3] := 'Expecto Patronum';
        Messages[4] := 'Homenum Revelio';

        for I := Low(Messages) to High(Messages) do
        begin
          WriteLn('Sending message[' + IntToStr(I) + ']: ' + Messages[I]);
          PublishResult := MQTTClient.Publish('devices/' + IOT_HUB_DEVICE_ID + '/messages/events/', Messages[I]);
          if PublishResult then
            WriteLn('Message sent successfully')
          else
            WriteLn('Failed to send message');
          Sleep(1000); 
        end;

        MQTTClient.Disconnect;
      finally
        SSL.Free;
      end;
    finally
      MQTTClient.Free;
    end;
  except
    on E: Exception do
      WriteLn('Error: ' + E.Message);
  end;
end.




输出:

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.