wing 发表于 2017-6-27 18:00:30

伪极客玩家乱入IoT之一 —— PC上的mqtt客户端程序开发

本帖最后由 wing 于 2017-6-28 09:18 编辑

直接简单地向大家介绍一个自行开发的mqtt客户端工具,本工具可以实现最基本的订阅和发布功能。本程序无需Java或者Python环境,是完整编译可以独立运行的win32程序(当然您得确保网络通畅和防火墙放行)。

特别鸣谢OCROBOT提供免费的mqtt服务,本工具默认使用该服务mqtt.ocrobot.com

运行效果如下





完全standalone的win32可执行程序


程序的完整代码


本程序实现了最最基本的mqtt客户端功能,而且是完全开源的。
楼下有如何开发这个程序的说明,如果您不太熟悉开发工具的话在阅读时可能遇到一些困惑。
之后会扩展这个程序来实现更多的功能,我觉得这是非常有趣,希望您也喜欢

wing 发表于 2017-6-27 18:59:54

本帖最后由 wing 于 2017-6-27 19:04 编辑

PS:下面这部分可能会变得比较难理解,原因可能是我也没搞得很清楚,不过幸运的是程序是能正常运作的。

物联网有无限的魅力,吸引了无数的极客。不过她的魅力远不止这样,连我这种伪极客真玩家都敢于乱入其中。
然而物联网是一个广泛的概念,如果您愿意的话大可以把完整的web服务应用在单片机上,而且事实上esp8266能很好地运行http服务。
但是为对得起自己的玩家属性,所以今天和大家谈谈主流IoT传输协议mqtt。
那么为选择mqtt?
原因是简单,实在太简单了,简单到完全不需要了解任何概念和理论都可以运用她。
只要有勇气和运气就足够了,如果您看了这么多废话还不打算关掉网页的话,那么您是幸运儿,因为本文就是为了解决运气问题的。

首先,我完全不懂mqtt服务器是怎么搭建的,不过不要紧,有人已经做好了,而且是免费的。
这里要感谢OCROBOT提供了优质的服务,下面的示例都是围绕ocrobot的服务进行的。
关于服务只需要知道两点:1主机地址mqtt.ocrobot.com;2端口1883。(很明显这个是公开的免费服务,无需用户ID和密码,完全开放)

其次,客户端我也不太明白,所以在github捡了个组件来挽救我的天真和无知。
对了,我其实是打算用delphi做一个简单的PC版mqtt客户端,版本是XE5。
如果您不打算使用这个开发工具也不要紧,本帖提供直接可以运行的程序给您试玩。

组件下载地址:https://github.com/pjde/delphi-mqtt
然后这个组件还依赖另一套网络组件:http://www.magsys.co.uk/download/wiki/icsv8w.zip
组件包里自带demo,不过这个例子太全面太复杂了,而且在没有VirtualStringTree的情况下是编译不过的。
所以我决定重写一个简单的,包括几个最基本功能:连接,断开,订阅,发布。
这几个功能分别对应程序界面上的几个按钮,这里要说明一下顺序:
第一步一定是连接;
第二步要先订阅;
第三步最后才是发布。

注意这种情况:
如果先订阅然后发布,订阅端可以收到发布的内容;
如果先发布再订阅,就收不到了。至少在most_once模式下是这样。

工程中的样子



主单元代码如下:
unit ufrm_mqtt_client;

interface

uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,uMQTT, uMQTTComps;

type
Tfrm_mqtt_client = class(TForm)
    MQTTClient1: TMQTTClient;
    Label1: TLabel;
    edt_host: TEdit;
    Label2: TLabel;
    edt_port: TEdit;
    btn_connect: TButton;
    btn_disconnect: TButton;
    Label3: TLabel;
    Label4: TLabel;
    edt_topic: TEdit;
    edt_message: TEdit;
    btn_sub: TButton;
    btn_pub: TButton;
    Memo_log: TMemo;
    procedure btn_connectClick(Sender: TObject);
    procedure btn_disconnectClick(Sender: TObject);
    procedure btn_subClick(Sender: TObject);
    procedure btn_pubClick(Sender: TObject);
    procedure MQTTClient1Msg(Sender: TObject; aTopic: UTF8String;
      aMessage: AnsiString; aQos: TMQTTQOSType; aRetained: Boolean);
    procedure FormShow(Sender: TObject);
private
    aQos : TMQTTQOSType;
    { Private declarations }
    procedure set_log(Astr:string);
public
    { Public declarations }
end;

var
frm_mqtt_client: Tfrm_mqtt_client;

implementation

{$R *.dfm}

procedure Tfrm_mqtt_client.FormShow(Sender: TObject);
begin
edt_topic.Text:='/dev_dmc/m'+IntToStr(GetTickCount)+'/';
edt_message.Text:='现在的时间是'+FormatDateTime('hhnnss',now);
end;

procedure Tfrm_mqtt_client.set_log(Astr:string);
begin
if Memo_log.Lines.Count>800 then
    Memo_log.Clear;

Memo_log.Lines.Add(DateTimeToStr(now)+ ' --->> '+Astr);
end;

procedure Tfrm_mqtt_client.btn_connectClick(Sender: TObject);
var
vport:Integer;
begin
if TryStrToInt(edt_port.Text,vport) then
begin
    try
      MQTTClient1.Port :=vport;
      MQTTClient1.Host:=edt_host.Text;
      MQTTClient1.Activate (true);

      set_log('连接成功');

      btn_connect.Enabled:=False;
      btn_disconnect.Enabled:=True;
      btn_sub.Enabled:=True;
      btn_pub.Enabled:=True;
    except
      on e:Exception do
      begin
      set_log('连接错误 :'+e.Message);
      end;
    end;
end
else
begin
    set_log('端口不是有效数字');
end;
end;

procedure Tfrm_mqtt_client.btn_disconnectClick(Sender: TObject);
begin
MQTTClient1.Activate (False);

set_log('断开连接');

btn_connect.Enabled:=True;
btn_disconnect.Enabled:=False;
btn_sub.Enabled:=False;
btn_pub.Enabled:=False;
end;

procedure Tfrm_mqtt_client.btn_subClick(Sender: TObject);
var
s:TStringlist;
begin
s:=TStringList.Create;
try
    s.AddObject(edt_topic.Text, TObject (aQos));
    MQTTClient1.Subscribe (s);

    set_log('订阅'+edt_topic.Text);
finally
    s.Free;
end;
end;

procedure Tfrm_mqtt_client.btn_pubClick(Sender: TObject);
begin
try
    MQTTClient1.Publish(edt_topic.Text, edt_message.Text, qtAT_MOST_ONCE, false);
    set_log('发布'+edt_topic.Text+' -> '+edt_message.Text);
except
    on e:Exception do
    begin
      set_log('发布错误 :'+e.Message);
    end;
end;
end;

procedure Tfrm_mqtt_client.MQTTClient1Msg(Sender: TObject; aTopic: UTF8String;
aMessage: AnsiString; aQos: TMQTTQOSType; aRetained: Boolean);
begin
set_log('收到订阅 "' + string (aTopic) + '".长度:'+IntToStr (length (aMessage)) + ' byte(s) @ ' + QOSNames);
set_log('信息内容:'+string (aMessage));
end;

end.

老胖熊 发表于 2017-6-28 10:14:01

有点复杂,要慢慢消化一下。

bg4iww 发表于 2017-6-28 15:52:53

看了一半天没看懂:L

wing 发表于 2017-6-30 09:48:08

看来大家都看不明白,强强也是这么说。
应该是我写的不清晰,其实我自己也不理解mqtt,但是作为玩家这个不是最重要的。
不懂无线电的人也能听广播,mqtt只是工具,就算不明原理,也能用她来做点什么。
下一帖来点现象级的东西:我要通过mqtt在互联网上控制一个云台

Freezing 发表于 2017-6-30 11:15:46

在外网也能控制?

wing 发表于 2017-7-3 11:11:05

internet访问没问题的。
其实没必要看明白上面的代码,因为顶楼已经提供了直接可执行的程序,下载直接用就可以了

maxims 发表于 2018-6-30 17:52:22

好东西啊~楼主能否开放一个服务端出来调试下客户端的硬件?

wing 发表于 2018-7-1 00:56:55

maxims 发表于 2018-6-30 17:52
好东西啊~楼主能否开放一个服务端出来调试下客户端的硬件?

服务是有的,由ocrobot.com提供,具体情况请看最顶楼

maxims 发表于 2018-7-20 17:16:26

wing 发表于 2018-7-1 00:56
服务是有的,由ocrobot.com提供,具体情况请看最顶楼

唉~以前不知道哪儿找到过一个本地服务端软件的~后来搞丢了。

wing 发表于 2018-7-21 11:28:34

maxims 发表于 2018-7-20 17:16
唉~以前不知道哪儿找到过一个本地服务端软件的~后来搞丢了。

这类软件有很多的,mqtt官方推荐的好像是 apache 的 apollo
不过目前为止我还没配置成功过 :(

“伪极客玩家乱入IoT”系列不只两篇的,之后还有更多玩法,当然这个系列都是和mqtt相关的,希望你喜欢

喔~~~稍微剧透一下,如果自己架设服务的话考虑下带加密协议的通讯方式,这样的话之后的体验会更好
页: [1]
查看完整版本: 伪极客玩家乱入IoT之一 —— PC上的mqtt客户端程序开发