主控芯片:MM32F2377 (MB-039)
WiFi 适配器:ESP8266
开发环境:IAR 7.80.4
MQTT 模拟服务器:MQTT.fx
MQTT is an OASIS standard messaging protocol for the Internet of Things (IoT). It is designed as an extremely lightweight publish/subscribe messaging transport that is ideal for connecting remote devices with a small code footprint and minimal network bandwidth. MQTT today is used in a wide variety of industries, such as automotive, manufacturing, telecommunications, oil and gas, etc.
—— mqtt.org
MQTT(Message Queuing Telemetry Transport) 消息队列遥测传输协议,是一个基于客户端-服务器的消息发布/订阅传输协议。主要的概念有5个:
我在这里使用的是第二个 MQTT.fx,用这个客户端模拟一下 MQTT 的 Publish/Subscribe。
首先在 EMQ 官网上找到 MQTT 接入信息,主要是 Broker 和 TCP 端口号

在接下来的模拟服务器使用中,Broker Address 可以直接用 broker-cn.emqx.io,也可以到查询网上查找对应的 IP 地址:47.111.117.220
EMQ 分为在国内有专门的服务器,连接更方便一些,国外的 Broker Address 是 broker.emqx.io
打开 MQTT.fx,点击齿轮状的设置按钮,填写 Broker Address,Port 等,再到 User Credentials 里填写用户名和密码,OK,Connect

连接成功后,发布消息:填 topic,我这里 topic 叫 esp8266,以 json 格式进行发送,点击 Publish

去订阅消息,切换到 Subscribe,订阅 esp8266 这个 topic,然后再发布消息,就可以在这里看到了

ESP8266 的介绍以及基本使用可查看上一篇 CSDN 「Rose Island」MM32F3277 + ESP8266 使用指南(1. 实现 TCP Client 透传)。
首先需要确认 AT 指令集具有 MQTT 指令:
具体的 MQTT AT 指令集可查阅:
配置 STA 模式:AT+CWMODE=1
连接路由器:AT+CWJAP="wifiName","wifiPsd"
配置 MQTT 属性:AT+MQTTUSERCFG=0,1,"clientID","username","password",0,0,""
连接制定的 MQTT broker:AT+MQTTCONN=0,"47.111.117.220",1883,0
查询 MQTT 连接状态:AT+MQTTCONN?
订阅 topic 数据:AT+MQTTSUB=0,"topicName",1
发布 topic 数据:AT+MQTTPUB=0,"topicName","payload",1,0
这里放的是与 MQTT 相关的函数,ESP8266 连网和 TCP 连接等函数可见「Rose Island」MM32F3277 + ESP8266 使用指南(1. 实现 TCP Client 透传)。
/// @brief Configure ESP8266 MQTT parameters.
/// @param clientId: Client ID num.
/// @param username: MQTT server username to log in MQTT broker.
/// @param psd: MQTT server password to log in MQTT broker.
/// @param scheme: Verification methods.
/// @retval None.
void ESP8266_MQTT_Init(char* clientId, char* username, char* psd, ESP8266_MQTT_Scheme_Typedef scheme)
{
ESP8266_MQTT_InitStruct.ipAddr.mqttIPAddr0 = ESP8266_MQTT_HOST_IPADDR_0;
ESP8266_MQTT_InitStruct.ipAddr.mqttIPAddr1 = ESP8266_MQTT_HOST_IPADDR_1;
ESP8266_MQTT_InitStruct.ipAddr.mqttIPAddr2 = ESP8266_MQTT_HOST_IPADDR_2;
ESP8266_MQTT_InitStruct.ipAddr.mqttIPAddr3 = ESP8266_MQTT_HOST_IPADDR_3;
ESP8266_MQTT_InitStruct.port = (uint32_t)ESP8266_MQTT_PORT;
ESP8266_MQTT_InitStruct.clientID = clientId;
ESP8266_MQTT_InitStruct.username = username;
ESP8266_MQTT_InitStruct.password = psd;
ESP8266_MQTT_InitStruct.scheme = scheme;
ESP8266_MQTT_InitStruct.mqttStatus = NO_INIT;
}
/// @brief Connect with MQTT server.
/// @param clientId: Client ID num.
/// @param username: MQTT server username to log in MQTT broker.
/// @param psd: MQTT server password to log in MQTT broker.
/// @param scheme: Verification methods.
/// @retval ESP8266 OK or ERROR.
ESP8266_Error_Typedef ESP8266_Connect_MQTT(char* clientId, char* username, char* psd, ESP8266_MQTT_Scheme_Typedef scheme)
{
ESP8266_MQTT_Init(clientId, username, psd, scheme);
char *cmd = (char*)malloc(256);
sprintf(cmd, "AT+MQTTUSERCFG=0,1,\"%s\",\"%s\",\"%s\",0,0,\"\"", clientId, username, psd);
if(ESP8266_Send_AT_Command_Times(cmd, "OK", 0xffff, 2)){
printf("Error: Fail to Configure MQTT \n");
return ESP8266_ERROR;
}else{
ESP8266_MQTT_InitStruct.mqttStatus = USERCFG_SET;
printf("OK: Configure MQTT successfully \n");
}
sprintf(cmd, "AT+MQTTCONN=0,\"%d.%d.%d.%d\",%d,0", ESP8266_MQTT_HOST_IPADDR_0, ESP8266_MQTT_HOST_IPADDR_1, ESP8266_MQTT_HOST_IPADDR_2, ESP8266_MQTT_HOST_IPADDR_3, ESP8266_MQTT_PORT);
if(ESP8266_Send_AT_Command_Times(cmd, "OK", 0xffff, 2)){
ESP8266_MQTT_InitStruct.mqttStatus = DISCONNECTED;
printf("Error: Fail to Connect MQTT \n");
return ESP8266_ERROR;
}else{
ESP8266_MQTT_InitStruct.mqttStatus = CONNECTED;
printf("OK: Connect MQTT successfully \n");
}
return ESP8266_OK;
}
/// @brief Check MQTT client state.
/// @param None.
/// @retval ESP8266 OK or ERROR.
ESP8266_Error_Typedef ESP8266_Check_MQTT()
{
char *cmd = "AT+MQTTCONN?";
if(ESP8266_Send_AT_Command_Times(cmd, "OK", 0xffff, 2)){
// printf("Error: Fail to Connect MQTT \n");
return ESP8266_ERROR;
}else{
// printf("OK: Connect MQTT successfully \n");
}
return ESP8266_OK;
}
/// @brief Subscribe topic from MQTT server.
/// @param subTopic: Subscribed topic name.
/// @retval ESP8266 OK or ERROR.
ESP8266_Error_Typedef ESP8266_MQTT_SUB(char* subTopic)
{
char *cmd = (char*)malloc(strlen("AT+MQTTSUB=0,\"%s\",1") + strlen(subTopic));
sprintf(cmd, "AT+MQTTSUB=0,\"%s\",1", subTopic);
if(ESP8266_Send_AT_Command_Times(cmd, "OK", 0xffff, 2)){
ESP8266_MQTT_InitStruct.mqttStatus = CONNECTED_NO_SUB;
printf("Error: Fail to Subscribe topic \n");
return ESP8266_ERROR;
}else{
ESP8266_MQTT_InitStruct.mqttStatus = CONNECTED_AND_SUB;
printf("OK: Subscribe topic successfully \n");
}
return ESP8266_OK;
}
/// @brief Unsubscribe topic from MQTT server.
/// @param subTopic: Unsubscribed topic name.
/// @retval ESP8266 OK or ERROR.
ESP8266_Error_Typedef ESP8266_MQTT_UNSUB(char* subTopic)
{
char *cmd = (char*)malloc(strlen("AT+MQTTUNSUB=0,\"\"") + strlen(subTopic));
sprintf(cmd, "AT+MQTTUNSUB=0,\"%s\"", subTopic);
if(ESP8266_Send_AT_Command_Times(cmd, "OK", 0xffff, 2)){
ESP8266_MQTT_InitStruct.mqttStatus = CONNECTED_NO_SUB;
printf("Error: Fail to Subscribe topic \n");
return ESP8266_ERROR;
}else{
ESP8266_MQTT_InitStruct.mqttStatus = CONNECTED_AND_SUB;
printf("OK: Subscribe topic successfully \n");
}
return ESP8266_OK;
}
/// @brief Publish topic to MQTT server.
/// @param subTopic: Publish topic name.
/// @retval ESP8266 OK or ERROR.
ESP8266_Error_Typedef ESP8266_MQTT_PUB(char* pubTopic, char* data)
{
char *cmd = (char*)malloc(strlen("AT+MQTTPUB=0,\"\",\"\",1,0") + strlen(pubTopic) + strlen(data));
sprintf(cmd, "AT+MQTTPUB=0,\"%s\",\"%s\",1,0", pubTopic, data);
if(ESP8266_Send_AT_Command_Times(cmd, "OK", 0xffff, 2)){
printf("Error: Fail to Publish topic \n");
return ESP8266_ERROR;
}else{
printf("OK: Publish topic successfully \n");
}
return ESP8266_OK;
}
/// @brief Disconnect with MQTT server.
/// @param None.
/// @retval ESP8266 OK or ERROR.
ESP8266_Error_Typedef ESP8266_MQTT_CLEAN()
{
char *cmd = "AT+MQTTCLEAN=0";
if(ESP8266_Send_AT_Command_Times(cmd, "OK\r\n", 0xffff, 2)){
printf("Error: Fail to Disconnect MQTT \n");
return ESP8266_ERROR;
}else{
ESP8266_MQTT_InitStruct.mqttStatus = NO_INIT;
printf("OK: Disconnect MQTT successfully \n");
}
return ESP8266_OK;
}
/// @brief Send key-value to MQTT.
/// @param dataSend: The whole key-value.
/// @param deviceId: Device id.
/// @param deviceType: Device type.
/// @param dataType: Data type.
/// @param dataValue: Data value.
/// @retval None.
void ESP8266_Data_Send(char *dataSend, char *deviceId, char *deviceType, char *dataType, float dataValue)
{
sprintf(dataSend,"{\r\n\"device_id\":\"%s\",\r\n\"device_type\":\"%s\",\r\n\"data_type\":\"%s\",\r\n\"data_value\":\"%.2f\"\r\n}",
deviceId, deviceType, dataType, dataValue);
printf("data sent is %s \n", dataSend);
}
typedef enum{
NO_INIT = (uint8_t)0,
USERCFG_SET = (uint8_t)1,
CONNCFG_SET = (uint8_t)2,
DISCONNECTED = (uint8_t)3,
CONNECTED = (uint8_t)4,
CONNECTED_NO_SUB = (uint8_t)5,
CONNECTED_AND_SUB = (uint8_t)6
} ESP8266_MQTT_Status_Typedef;
typedef enum{
NO_TLS = (uint8_t)1,
TLS_NO_CA = (uint8_t)2,
TLS_SERVICE_CA = (uint8_t)3,
TLS_CLIENT_CA = (uint8_t)4,
TLS_SERVICE_CLIENT_CA = (uint8_t)5,
WS_TCP = (uint8_t)6,
WSS_NO_CA = (uint8_t)7,
WSS_SERVICE_CA = (uint8_t)8,
WSS_CLIENT_CA = (uint8_t)9,
WSS_SERVICE_CLIENT_CA = (uint8_t)10
} ESP8266_MQTT_Scheme_Typedef;
#define ESP8266_MQTT_CLIENTIP "mm32f3270"
#define ESP8266_MQTT_USERNAME "mm32"
#define ESP8266_MQTT_PSD "mm32psd"
#define ESP8266_MQTT_HOST "broker-cn.emqx.io"
#define ESP8266_MQTT_HOST_IPADDR_0 47
#define ESP8266_MQTT_HOST_IPADDR_1 111
#define ESP8266_MQTT_HOST_IPADDR_2 117
#define ESP8266_MQTT_HOST_IPADDR_3 220
#define ESP8266_MQTT_PORT 1883
#define ESP8266_MQTT_TOPIC "esp8266"
typedef struct
{
uint8_t mqttIPAddr0;
uint8_t mqttIPAddr1;
uint8_t mqttIPAddr2;
uint8_t mqttIPAddr3;
}ESP8266_MQTT_IPADDR_Typedef;
typedef struct
{
ESP8266_MQTT_IPADDR_Typedef ipAddr;
uint32_t port;
char* clientID;
char* username;
char* password;
ESP8266_MQTT_Scheme_Typedef scheme;
ESP8266_MQTT_Status_Typedef mqttStatus;
} ESP8266_MQTT_Typedef;
ESP8266_MQTT_Typedef ESP8266_MQTT_InitStruct;
🙏🙏🙏🙏🙏🙏🙏
我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以
我使用的是Firefox版本36.0.1和Selenium-Webdrivergem版本2.45.0。我能够创建Firefox实例,但无法使用脚本继续进行进一步的操作无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055)错误。有人能帮帮我吗? 最佳答案 我遇到了同样的问题。降级到firefoxv33后一切正常。您可以找到旧版本here 关于ruby-无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055),我们在StackOverflow上找到一个类
require"socket"server="irc.rizon.net"port="6667"nick="RubyIRCBot"channel="#0x40"s=TCPSocket.open(server,port)s.print("USERTesting",0)s.print("NICK#{nick}",0)s.print("JOIN#{channel}",0)这个IRC机器人没有连接到IRC服务器,我做错了什么? 最佳答案 失败并显示此消息::irc.shakeababy.net461*USER:Notenoughparame
考虑一下:现在这些情况:#output:http://domain.com/?foo=1&bar=2#output:http://domain.com/?foo=1&bar=2#output:http://domain.com/?foo=1&bar=2#output:http://domain.com/?foo=1&bar=2我需要用其他字符串输出URL。我如何保证&符号不会被转义?由于我无法控制的原因,我无法发送&。求助!把我的头发拉到这里:\编辑:为了澄清,我实际上有一个像这样的数组:@images=[{:id=>"fooid",:url=>"http://
我有一个super简单的脚本,它几乎包含了FayeWebSocketGitHub页面上用于处理关闭连接的内容:ws=Faye::WebSocket::Client.new(url,nil,:headers=>headers)ws.on:opendo|event|p[:open]#sendpingcommand#sendtestcommand#ws.send({command:'test'}.to_json)endws.on:messagedo|event|#hereistheentrypointfordatacomingfromtheserver.pJSON.parse(event.d
我有一个ruby脚本可以打开与Apple推送服务器的连接并发送所有待处理的通知。我看不出任何原因,但当Apple断开我的脚本时,我遇到了管道损坏错误。我已经编写了我的脚本来适应这种情况,但我宁愿只是找出它发生的原因,这样我就可以在第一时间避免它。它不会始终根据特定通知断开连接。它不会以特定的字节传输大小断开连接。一切似乎都是零星的。您可以在单个连接上发送的数据传输或有效负载计数是否有某些限制?看到人们的解决方案始终保持一个连接打开,我认为这不是问题所在。我看到连接在3次通知后断开,我看到它在14次通知后断开。我从未见过它能超过14点。有没有人遇到过这种类型的问题?如何处理?
我的意思是之前建立的那个DB=Sequel.sqlite('my_blog.db')或DB=Sequel.connect('postgres://user:password@localhost/my_db')或DB=Sequel.postgres('my_db',:user=>'user',:password=>'password',:host=>'localhost')等等。Sequel::Database类没有名为“disconnect”的公共(public)实例方法,尽管它有一个“connect”。也许有人已经遇到过这个问题。我将不胜感激。 最佳答案
我有一个遗留数据库,我正在努力让ActiveRecord使用它。我遇到了连接表的问题。我有以下内容:classTvShow然后我有一个名为tvshowlinkepisode的表,它有2个字段:idShow、idEpisode所以我有2个表和它们之间的连接(多对多关系),但是连接使用非标准外键。我的第一个想法是创建一个名为TvShowEpisodeLink的模型,但没有主键。我的想法是,由于外键是非标准的,我可以使用set_foreign_key并进行一些控制。最后,我想说一些类似TvShow.find(:last).episodes或Episode.find(:last).tv_sho
我正在使用PostgreSQL9.1.3(x86_64-pc-linux-gnu上的PostgreSQL9.1.3,由gcc-4.6.real(Ubuntu/Linaro4.6.1-9ubuntu3)4.6.1,64位编译)和在ubuntu11.10上运行3.2.2或3.2.1。现在,我可以使用以下命令连接PostgreSQLsupostgres输入密码我可以看到postgres=#我将以下详细信息放在我的config/database.yml中并执行“railsdb”,它工作正常。开发:adapter:postgresqlencoding:utf8reconnect:falsedat
在字符串连接中,是否可以直接在语句中包含条件?在下面的示例中,我希望仅当dear列表不为空时才连接"mydear"。dear=""string="hello"+"mydear"unlessdear.empty?+",goodmorning!"但是结果报错:undefinedmethod'+'fortrue我知道另一种方法是在这条语句之前定义一个额外的变量,但我想避免这种情况。 最佳答案 使用插值而不是连接更容易和更具可读性:dear=""string="hello#{'mydear'unlessdear.empty?},goodmo