Delphi MQTT 2019/09/01

IoT 通信プラットフォームサービス SenseWay (センスウェイ)の LoRaWAN MQTT接続に関するマニュアル を Delphi でやってみました。

 Delphi の Getit パッケージマネージャからインストールできる 「Trial - TMS MQTT」 コンポーネントを使っています。
 

 Delphi で MQTT サーバからのデータ取得 (Subscribe)、書き込み (Publish) ができます。
 

 SenseWay Mission Connect から行える「デバイスへのデータ送信」が、Delphi でも行えるということです。
 

で、具体的に何に使うのか・・・。
例えば、
 ・ Delphi で作った Android アプリで IoT 端末から送信された(その時点の)データを見る。
 ・ Delphi で作った Android アプリから IoT 端末へデータを送信する。→ 端末デバイスで出力値、設定値を変えるとか。
  IoT 端末に Arduino を使っているので、いろんなことに使えそうです。


// Delphi 10.3 Community Edition
unit TMQTT_TESTUnit4;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, TMS.MQTT.Global, Vcl.StdCtrls,
  TMS.MQTT.Client;

type
  TForm4 = class(TForm)
    TMSMQTTClient1: TTMSMQTTClient;
    Button1: TButton;
    Memo1: TMemo;
    Button2: TButton;
    Button3: TButton;
    Button4: TButton;
    procedure Button1Click(Sender: TObject);
    procedure TMSMQTTClient1SubscriptionAcknowledged(ASender: TObject;
      APacketID: Word; ASubscriptions: TTMSMQTTSubscriptions);
    procedure Button2Click(Sender: TObject);
    procedure TMSMQTTClient1PublishReceived(ASender: TObject; APacketID: Word;
      ATopic: string; APayload: TArray<System.Byte>);
    procedure TMSMQTTClient1PublishReceivedEx(ASender: TObject; APacketID: Word;
      ATopic: string; APayload: TTMSMQTTBytes);
    procedure Button3Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
    FSubscribeRequestPacketId : Word;
  end;

var
  Form4: TForm4;

implementation

{$R *.dfm}

const
  HostName = 'mqtt.senseway.net';
  UserName = 'xxxxx';
  PassWord = 'yyyyyyyyy';
  devEUI   = 'zzzzzzzzzzzzzz';


procedure TForm4.Button1Click(Sender: TObject);
// 接続
begin
  TMSMQTTClient1.BrokerHostName := HostName;
  TMSMQTTClient1.BrokerPort := 1883;

  TMSMQTTClient1.ClientID := UserName;
  TMSMQTTClient1.Credentials.Username := UserName;
  TMSMQTTClient1.Credentials.Password := PassWord;

  TMSMQTTClient1.LastWillSettings.Topic := '';

  // 接続
  TMSMQTTClient1.Connect();
end;

procedure TForm4.Button2Click(Sender: TObject);
// Subscribe
begin
  // MQTTでSubscribeすればデータを取得することができる
  if TMSMQTTClient1.IsConnected then begin
    Memo1.Lines.Clear;

    FSubscribeRequestPacketId :=
      TMSMQTTClient1.Subscribe(
        'lora/' + UserNAme + '/+/#',   // ワイルドカード(すべてのデータ)
        //'lora/'+ UserName+ '/+/rx', // 受信データのみの時
         TTMSMQTTQoS.qosAtMostOnce
      );
  end;
end;

procedure TForm4.Button3Click(Sender: TObject);
// Publish
var
  APayload : TBytes;
  s : string;
begin
  // データ書き込み
  s := '{"conf":false,"ref":"fghij","port":16,"data":"04d2"}';
  APayload := TEncoding.ANSI.GetBytes(s);

  if TMSMQTTClient1.IsConnected then begin
    TMSMQTTClient1.Publish(
      'lora/' + UserName + '/' + devEUI + '/tx',
       APayload,
       TTMSMQTTQoS.qosAtMostOnce,
       True
    );
  end;
end;

procedure TForm4.Button4Click(Sender: TObject);
// Disconnect
begin
  // 切断
  if TMSMQTTClient1.IsConnected then begin
    TMSMQTTClient1.Disconnect;
  end;
end;

procedure TForm4.TMSMQTTClient1PublishReceived(ASender: TObject;
  APacketID: Word; ATopic: string; APayload: TArray<System.Byte>);
begin
  Memo1.Lines.Add(#13#10 + 'Topic = ' + ATopic);
  Memo1.Lines.Add('Payload = ' + TEncoding.ANSI.GetString(APayload));
end;

procedure TForm4.TMSMQTTClient1PublishReceivedEx(ASender: TObject;
  APacketID: Word; ATopic: string; APayload: TTMSMQTTBytes);
begin
  // こちらも同じ結果
  Memo1.Lines.Add(#13#10 + FormatDateTime('YYYY/MM/DD hh:nn:ss', Now));
  Memo1.Lines.Add('TopicEx = ' + ATopic);
  Memo1.Lines.Add('PayloadEx = ' +  TEncoding.ANSI.GetString(APayload));
end;

procedure TForm4.TMSMQTTClient1SubscriptionAcknowledged(ASender: TObject;
  APacketID: Word; ASubscriptions: TTMSMQTTSubscriptions);
begin
  if (APacketID = FSubscribeRequestPacketId) and ASubscriptions[0].Accepted then begin
    Memo1.Lines.Add('We are subscribed!');
  end;
end;

end.