本帖最后由 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[aQos]);
- set_log('信息内容:'+string (aMessage));
- end;
- end.
复制代码
|