还是之前的那个事情,找个物联网模拟器小工具实在是找不到了,只能自己抽空写个小工具了。qmqtt库已经安装好了,关于qmqtt协议的学习已经看的差不多了,然后就写了这个小工具。
既然有了qmqtt库,那就实例化一个qmqtt的client,然后将里面的主要信号连接到槽函数,在槽函数里进行一系列相关的操作。当然,肯定需要一些用户交互的按钮、输入框什么的,大概的画个思路吧。
1、实例化qmqtt的client,设置槽函数
client = new QMQTT::Client();
connect(client,SIGNAL(connected()),this,SLOT(doConnected()));
connect(client,SIGNAL(disconnected()),this,SLOT(doDisconnected()));
connect(client,SIGNAL(received(QMQTT::Message)),this,SLOT(doDataReceived(QMQTT::Message)));
connect(client,SIGNAL(error(QMQTT::ClientError)),this,SLOT(doError(QMQTT::ClientError)));
2、连接参数计算
这里是个关键点,最主要的就是如何生成连接需要的参数。这里有两个需要注意的问题:
第一、获取的字符串必须要转一下格式。具体如下所示:
//配置MQTT连接参数
client->setHostName(hostname.toLatin1());// toLatin1()将字符串转换为QByteArray,系统已经设置编码默认utf-8
client->setPort(1883);
client->setClientId(client_id.toLatin1());
client->setUsername(username.toLatin1());
client->setPassword(password.toLatin1());
第二、关于Hmacsha1签名算法
阿里云的用户密码需要用Hmacsha1算法进行计算,算法是公开的,QT官网也有:https://wiki.qt.io/HMAC-SHA1。大家可以去看看,我也是参照这个链接进行计算的。但是,重点在于一定要把最后的返回值格式改成Hex的,不能是qbase64,因为阿里云的密码是hex的,下面是修改之后的算法:
/**
* @brief MainWindow::hmacSha1
* hmacsha1算法,计算密码
* @param key
* @param baseString
* @return
*/
QString MainWindow::hmacSha1(QByteArray key, QByteArray baseString)
{
int blockSize = 64; // HMAC-SHA-1 block size, defined in SHA-1 standard
if (key.length() > blockSize) { // if key is longer than block size (64), reduce key length with SHA-1 compression
key = QCryptographicHash::hash(key, QCryptographicHash::Sha1);
}
QByteArray innerPadding(blockSize, char(0x36)); // initialize inner padding with char "6"
QByteArray outerPadding(blockSize, char(0x5c)); // initialize outer padding with char "quot;
for (int i = 0; i < key.length(); i++) {
innerPadding[i] = innerPadding[i] ^ key.at(i); // XOR operation between every byte in key and innerpadding, of key length
outerPadding[i] = outerPadding[i] ^ key.at(i); // XOR operation between every byte in key and outerpadding, of key length
}
QByteArray total = outerPadding;
QByteArray part = innerPadding;
part.append(baseString);
total.append(QCryptographicHash::hash(part, QCryptographicHash::Sha1));
QByteArray hashed = QCryptographicHash::hash(total, QCryptographicHash::Sha1);
return hashed.toHex();//此处必须为tohex,因为阿里云的是hex
}
还有,把需要的参数按照阿里云的要求组合起来,计算所有需要的参数,这应该算是个小苦力活了。没啥说的。
3、连接成功
/**
* @brief MainWindow::doConnected
* 连接代理
*/
void MainWindow::doConnected()
{
qDebug() << "doConnected !!!!!!!!!";
QString currentTime = QDateTime::currentDateTime().toString("yyyy.MM.dd hh:mm:ss");
QString log = currentTime +" 连接成功!" + "\n";
ui->te_log->append(log);
ui->linkSta->setStyleSheet(ledGreen_Style_small);
ui->pb_connect->setText("Disconnect");
ui->publishBtn->setEnabled(true);
ui->subscribeBtn->setEnabled(true);
ui->unSubscribeBtn->setEnabled(true);
}
4、连接失败
/**
* @brief MainWindow::doDisconnected
* 断开连接
*/
void MainWindow::doDisconnected()
{
qDebug() << "doDisconnected";
paraEnFlag = 1;
contrlPara();
QString currentTime = QDateTime::currentDateTime().toString("yyyy.MM.dd hh:mm:ss");
QString log = currentTime +" 连接断开!" + "\n";
ui->te_log->append(log);
ui->linkSta->setStyleSheet(ledRed_Style_small);
ui->pb_connect->setText("Connect");
ui->publishBtn->setEnabled(false);
ui->subscribeBtn->setEnabled(false);
ui->unSubscribeBtn->setEnabled(false);
}
5、接收消息
/**
* @brief MainWindow::doDataReceived
* 接收消息
* @param message
*/
void MainWindow::doDataReceived(Message message)
{
QString currentTime = QDateTime::currentDateTime().toString("yyyy.MM.dd hh:mm:ss");
QString mes = currentTime + " " + QString::number(message.id())+ " | " + QString::number(message.qos())+ " | " +message.topic()+ " | " + message.payload() + "\n";
ui->te_log->append(mes);
qDebug() << "doDataReceived";
}
6、发布消息
/**
* @brief MainWindow::on_publishBtn_clicked
* 发布消息
*/
void MainWindow::on_publishBtn_clicked()
{
qDebug() << "on_pushButton_clicked";
QString currentTime = QDateTime::currentDateTime().toString("yyyy.MM.dd hh:mm:ss");
QString topic = ui->le_pb_topic->text().trimmed();
QString payload = ui->le_pu_payload->toPlainText();//text().trimmed();
if(topic.isEmpty() || payload.isEmpty())
{
qDebug()<<"pub topic and payload is empty!"<te_log->append(log);
return;
}
QMQTT::Message message(136,topic,payload.toUtf8());
client->publish(message);
QString mes = currentTime +" "+ QString(message.id())+" "+QString(message.qos())+" "+message.topic()+" "+message.payload()+"\n";
ui->te_log->append(mes);
}
嗯。。。大概就是这么多,其他的关于qmqtt库的使用,可以看我的上一个博文:https://blog.csdn.net/yimuta9538/article/details/104010393。
关注公众号“码代码”,公众号发送“阿里云”,获取免费下载连接。
解压密码:“madaima”