MQTT 协议

VuGen 的 MQTT 协议支持使用机对机 (M2M) 和物联网 (IoT) 通信的网络测试。

关于 MQTT

MQTT 是一种为受约束的设备和低带宽、高延迟或不可靠网络而设计的简单的轻型发布/订阅消息协议,。

MQTT 是 M2M 和 IoT 通信以及带宽和电池电量极为宝贵的移动应用程序的理想选择。MQTT 致力于最大程度地减少网络带宽和设备资源要求,同时尝试确保可靠性和一定程度的交付保证。

MQTT 使用发布者-订阅者操作来进行客户端和服务器之间的通信。MQTT 服务器是控制客户端之间通信的消息代理。

客户端或“内容”可以是发布者或订阅者。

  • “发布者”是发送消息的客户端。消息将转到消息代理,并指定一个主题。
  • “订阅者”是接收消息的客户端。要接收有关主题的消息,订阅者必须订阅它。

返回顶部

创建 MQTT 脚本

您可以使用 MQTT 脚本向导为脚本生成属性,也可以使用定义的 MQTT 函数手动对其进行脚本编写。

脚本的客户端变量在“额外文件”> globals.h 文件中进行声明,可以从解决方案资源管理器访问该文件。

要创建 MQTT 脚本,请执行以下操作:

  1. 通过选择“新建脚本和解决方案”>“MQTT 协议”创建新脚本。

    一个即用型脚本在编辑器中打开,其中使用了所有可用的 MQTT 函数。此外,“脚本向导”会在单独的对话框中自动打开。

  2. 按下列方法之一设计脚本:

    • 使用脚本向导生成脚本。有关详细信息,请参阅MQTT 脚本向导
    • 单击“取消”关闭脚本向导,然后根据需要修改即用型脚本模板。有关 MQTT 函数和函数调用的完整说明,请参阅函数参考

    注: 如果要创建多协议脚本,则可以将 MQTT 步骤集成到录制的 Web - HTTP/HTML 脚本中。有关详细信息,请参阅使用多协议脚本

  3. 配置运行时设置。这些设置会影响 Vuser 脚本的运行方式。

    1. 在解决方案资源管理器中,双击“运行时设置”

    2. 在“<测试名称>:运行时设置”视图中,根据需要配置运行时设置。要查看各个运行时设置的描述,请将光标悬停在运行时设置字段名称上。

    有关一般详细信息,请参阅运行时设置配置运行时设置

返回顶部

MQTT 脚本向导

通过 MQTT 脚本向导,可以定义设置,然后在 MQTT 脚本中将其作为代码生成。

新建 MQTT 脚本时,将自动显示脚本向导 (默认设置)。您也可以通过单击 VuGen 工具栏上的“设计脚本”来打开它。(在编辑器中打开 MQTT 脚本时,可使用“设计脚本”按钮。)

UI 元素

描述

连接设置选项卡
代理 URL

代理服务器的地址,格式为: tcp://host:portssl://host:port,其中 host 是域名、IPv4 地址或 IPv6 地址,位于方括号中。IPv6 地址示例: [2001:0db8:85a3:0000:0000:8a2e:0370:7334]。

如果未指定端口,则使用以下默认端口:

  • tcp://host:1883
  • ssl://host:8883
客户端 ID

定义连接的客户端 ID。该字符串是网络中客户端的唯一标识符。将该字段留空则使用自动生成的 ID。

客户端标识如下:

  • 如果新建客户端 (由“客户端 ID”标识),则在生成脚本时,将使用向导中的所有属性将新客户端附加到现有脚本中。

    自动生成的 ID 始终会新建一个客户端。

  • 如果“客户端 ID”在脚本中已经具有连接,则将其视为现有客户端。在这种情况下,仅将其他属性附加到现有客户端。请参阅客户端的其他属性
身份验证设置 如果需要,定义用户名和密码以登录代理服务器。
启用 TLS 选择是否需要通过 TLS (SSL) 进行安全通信,然后从下拉列表中选择相关的“TLS 版本”。如果选择“默认值”,则使用运行时设置中定义的版本。
使用客户端证书

选择以使用客户端证书,然后定义证书文件和私钥的路径以及密钥的密码 (如果密钥未加密,则将密码字段留空)。

检查连接 单击以检查 VuGen 是否可以使用定义的凭据成功连接到代理。如果连接成功,将显示一个绿勾;如果连接失败,将显示一个红叉。
针对新脚本显示向导

如果不希望在新建 MQTT 脚本时自动打开脚本向导,则清除该复选框。

提示: 如果脚本向导没有自动打开,则可以通过单击 VuGen 工具栏中的“设计脚本”来打开它。

全部清除 单击以清除所有选项卡中的所有设置。
生成代码 如果启用了该按钮,则单击以将相关步骤添加到脚本代码中;否则,继续前进到后续选项卡以定义可选设置。
客户端设置选项卡
发布者/订阅者

为这些选项之一定义值。使用单选按钮在它们之间切换:

  • 发布者: 定义发布消息的设置。
  • 订阅者: 为订阅者定义主题。

要发布的主题 用于发布消息的目标主题,例如: myhome/kitchen/temperature/1
负载 以字节格式设置要发布的消息。
保留消息

选中后,指示代理将主题中最后保留的消息及其 QoS 一起存储。每个主题仅存储一条消息,因此最后保留的消息将始终替换任何先前存储的消息。

这对于在新订阅者订阅主题时向其提供最新状态非常有用,因此他们无需等待下一个状态更新。

服务质量

所需的服务质量 (QoS)。例如,如果在 QoS = 0 的情况下失去连接,则客户端在重新连接后不会尝试再次发布,并且脚本输出中将显示警告。

值为 0 到 2 和默认值 (在运行时设置中定义)。

要订阅的主题

用于使客户端订阅一个主题或一组主题 (通过使用通配符)。代理自动发送有关这些主题的消息。主题可以包含通配符。

示例:

myhome/kitchen/temperature/1, region2/#

region2/WeatherStation/+/temperature

使用在运行时设置中定义的默认 QoS。

Last Will 和 Testament 选项卡
主题 定义目标主题,以将某客户端非正常断开连接的信息通知给其他客户端。
负载 设置客户端意外断开连接时代理发送给指定主题订阅者的消息。
保留消息 选中后,指示代理将最后保留的消息存储在此主题中。每个主题仅存储一条消息,因此最后保留的消息将始终替换任何先前存储的消息。

客户端的其他属性

您可以使用 MQTT 脚本向导为现有客户端 (在脚本中已有连接的客户端) 定义其他属性。客户端由向导中提供的“客户端 ID”定义。

可能的其他属性有:

  • 发布者。一个客户端可以有多个发布者。如果为现有客户端创建了发布者,则新发布者添加到相应客户端的 Actions.c 文件中。

  • 订阅者。客户端一次只能订阅一个主题。如果为现有客户端创建了订阅者,则代码生成将验证现有客户端是否已经订阅。如果它有一个订阅者,则忽略向导中的订阅者。否则,将订阅者添加到 vuser_init.c 文件中的 client_settings() 函数中,并在 vuser_end.c 文件中相应的客户端断开连接之前添加相应的取消订阅。

  • Last Will 和 Testament。一个客户端只能有一条 Last Will 和 Testament (LWT) 消息。如果为现有客户端创建了 LWT 消息,则代码生成将验证现有客户端是否已有 LWT。如果已有,则忽略向导中的 LWT 消息。如果没有,则新的 LWT 函数添加到 vuser_init.c 文件的 client_settings() 函数中的相应客户端。

返回顶部

使用多协议脚本

您可以测试脚本同时使用以下两个协议的场景:

  • MQTT 在客户端和代理之间进行通信

  • Web - HTTP/HTML 以在代理和 Web 应用程序之间进行通信

您可以通过在 Web 应用程序上录制步骤来准备脚本。然后根据需要手动添加 MQTT 步骤。使用多协议脚本时不包括预填充的 MQTT 脚本,但是您可以从即用型 MQTT 脚本模板中复制/粘贴。

要启用支持,请执行以下操作:

  1. 创建一个包含 MQTT 和 Web - HTTP/HTML 的多协议脚本。有关详细信息,请参阅创建新脚本对话框

  2. 录制 Web 脚本。

    注: 录制 Web 脚本会覆盖 globals.h,从而移除对 MQTT 步骤的默认支持。

  3. 恢复对 MQTT 步骤的支持:

    1. 打开 globals.h (位于解决方案资源管理器中的“额外文件”下)。

    2. #include "MqttApi.h" 添加到 Include Files 部分。

  4. 将 MQTT 步骤添加到脚本中。

多协议脚本示例

Action()
{
  MQTT client;
	
  client = mqtt_create();
	
  mqtt_set_client_id(client, "myclientid");
	
  lr_start_transaction("connect_MQTT");
	
  mqtt_connect(client, "tcp://mymachine:1883");
	
  lr_end_transaction("connect_MQTT", LR_AUTO);
	
  lr_start_transaction("navigate_Web");		

  // your recorded web code here						
					
  lr_end_transaction("navigate_Web", LR_AUTO);
						
  mqtt_publish(client, "topic/subtopic", "payload", MQTT_AUTO, MQTT_DEFAULT, MQTT_NORETAIN);
                     
  mqtt_disconnect(client);
	

  return 0; 
}

返回顶部

即用型 MQTT 脚本模板

默认的单协议 MQTT 脚本包含预先填充带注释步骤的操作 (如下所示)。

在使用多协议脚本时,首先要在 Web 应用程序上录制步骤。然后根据需要添加 MQTT 步骤。可以从下面的模板复制/粘贴相关步骤。

有关这些函数的详细信息,请参阅函数参考

vuser_init

vuser_init()
{
  /* Declared in "globals.h" */
  client = mqtt_create();
	
  /* Optional connection settings */
  // mqtt_set_client_id(client, "<insert Client ID>");
  // mqtt_set_credentials(client, "<username placeholder>", "<password placeholder>");
  // mqtt_set_lwt(client, "<topic>", "<sample lwt payload>", MQTT_AUTO, MQTT_DEFAULT, MQTT_RETAIN);
	
	
  /* Optional SSL/TLS settings, applicable for SSL/TLS connections only */
  // mqtt_set_tls_certificate(client, "<path to a certificate file, e.g. cert.pem>", "<path to a private key file, e.g. key.pem>", "<password for the private key>");
  // mqtt_set_tls_parameters(client, MQTT_TLS_DEFAULT, MQTT_DEFAULT_CIPHERS);
	
  /* Connect to an MQTT broker */
  mqtt_connect(client, "tcp://<enter an MQTT broker host name>");
	
  /* Uncomment the following if implementing the "subscriber" logic */
  // mqtt_subscribe(client, "<topic>");
  return 0; 
}		

操作

Action()
{
  /* Uncomment the following if implementing the "subscriber" logic.Make sure to also uncomment subscribe/unsubscribe in vuser_init/end.c */
  //
  /* Option 1: Wait for messages, then handle their contents */
  // size_t messageCount = mqtt_await_messages(client, MQTT_DEFAULT);
  // size_t i = 0;
  // for ( ; i < messageCount; i++)
	   
  // {
  // MQTT_MESSAGE m = mqtt_read_inbox(client);
  // const char* p = mqtt_get_payload(m);
  // const char* t = mqtt_get_topic(m);
  // size_t l = mqtt_get_length(m);
  // ... do something meaningful with the message
  // ... for instance, print received message information (assuming its payload is not binary data)
  // lr_message("received message with size %d from %s", l, t);
  // lr_message("payload %.*s", l, p);
  //
  // mqtt_free_message(m);
  // }
	  
  /* Option 2: Wait for messages, then clear Inbox (if their handling is not needed) */
  // mqtt_await_messages(client, MQTT_DEFAULT);
  // mqtt_clear_inbox(client);
				  
  /* Uncomment the following if implementing the "publisher" logic */
  // mqtt_publish(client, "<topic>", "<payload>", MQTT_AUTO, MQTT_DEFAULT, MQTT_RETAIN);
				  
  return 0; 
}

vuser_end

vuser_end()
{
  /* Uncomment the following if implementing the "subscriber" logic */	
  // mqtt_unsubscribe(client, "<topic>");
	
  /* Disconnect from the MQTT broker */
  mqtt_disconnect(client);
	
  return 0; 
}
		

返回顶部