目录
本项目的交流QQ群:701889554
物联网实战--入门篇https://blog.csdn.net/ypp240124016/category_12609773.html
物联网实战--驱动篇https://blog.csdn.net/ypp240124016/category_12631333.html
本项目资源文件 https://download.csdn.net/download/ypp240124016/89317308
一、分组数据库
如上图所示,后台系统会为每一个应用创建一个文件夹,用于存放该应用的数据库,目前这里的appInfo.db主要是分组库表和设备列表,数据库内容如下,目前还没有设备信息。
cpp
bool GroupSqlite::createGroupTable(void)
{
QString str_query = QString::asprintf("CREATE TABLE If Not Exists group_tb ("
"groupName varchar(1000) NOT NULL,"
"groupOrder INTEGER DEFAULT 1000,"
"devList varchar(10000) DEFAULT 0,"
"createTime timestamp DEFAULT (datetime(\'now\',\'localtime\')),"
"PRIMARY KEY (groupName)"
")"
);
// qDebug()<<"str_query= "<<str_query;
if(runSqlQuery(str_query)==false)
{
qDebug()<<"createGroupTable error";
return false;
}
else
{
qDebug()<<"createGroupTable ok: ";
}
return true;
}
以上是分组数据库创建库表的代码,里面有一个groupOrder字段,默认值是1000,在分组排序的时候会用到,当有排序指令时,后台会按照上传的分组列表从0开始,按顺序更新这个groupOrder值,读取的时候按groupOrder的升序读取就可以达到排序的目的了。以下是读取分组列表的代码,SQL语句中的ASC就是升序读取的意思。
cpp
bool GroupSqlite::selectGroupList(QList<GroupNodeStruct> &groupList)
{
QString str_query = QString::asprintf("SELECT groupName, groupOrder, devList, createTime FROM group_tb ORDER BY groupOrder ASC");
// qDebug()<<str_query;
if(runSqlQuery(str_query)==false)
{
qDebug("selectGroupList error_01!");
return false;
}
while(m_sqlQuery.next())
{
int ptr=0;
GroupNodeStruct tag_group_node;
tag_group_node.groupName=m_sqlQuery.value(ptr++).toString();
tag_group_node.groupOrder=m_sqlQuery.value(ptr++).toUInt();
tag_group_node.devList.clear();
QString json_str=m_sqlQuery.value(ptr++).toString();
QByteArray json_ba=QByteArray::fromBase64(json_str.toUtf8());
QJsonParseError json_error;
QJsonDocument json_doc;
json_doc = QJsonDocument(QJsonDocument::fromJson(json_ba, &json_error));//转为JSON格式
if(json_error.error != QJsonParseError::NoError)
{
qDebug()<<"json error= "<<json_error.error;
}
else
{
QJsonObject root_obj = json_doc.object();
if(root_obj.contains("dev_list"))//设备列表
{
QJsonValue value=root_obj.value("dev_list");
if(value.isArray())
{
QJsonArray dev_array=value.toArray();
int nSize=dev_array.size();
for(int i=0; i<nSize; i++)
{
QJsonValue value=dev_array.at(i);
if(value.isDouble())
{
u32 dev_sn=value.toDouble();
if(dev_sn>0)
{
tag_group_node.devList.append(dev_sn);//添加dev_sn
}
}
}
}
}
}
tag_group_node.createTime=m_sqlQuery.value(ptr++).toString();
groupList.append(tag_group_node);
}
m_sqlQuery.finish();
return true;
}
数据库的其它操作都算比较常规的,自行阅读代码。
二、请求分组列表
用户后端请求代码如下:
cpp
void CenterMan::requestGroupList(void)
{
QJsonObject root_obj;
QJsonDocument json_doc;
root_obj.insert("account", m_loginAccount);
root_obj.insert("rand_num", m_randNum);
root_obj.insert("mac", m_macStr);
root_obj.insert("app_id", (qint64)m_currAppWork.appID);
root_obj.insert("cmd_type", "group_list");
json_doc.setObject(root_obj);
QByteArray msg_ba = json_doc.toJson(QJsonDocument::Indented);
QString topic=makePubTopic("group");
emit sigMqttPushMessage(topic, msg_ba);
}
服务器收到请求指令后读取数据并返回:
cpp
if(cmd_type=="group_list")
{
QList<GroupSqlite::GroupNodeStruct>group_list;
tag_groupSqlite.selectGroupList(group_list);
for(auto iter : group_list)
{
QJsonObject group_obj;
QJsonArray dev_list;
for(auto iter2 : iter.devList)
{
u32 dev_sn=iter2;
dev_list.append((qint64)dev_sn);
}
group_obj.insert("group_name", iter.groupName);
group_obj.insert("dev_list", dev_list);
group_array.append(group_obj);
}
ackTakeGroupList(account, mac_str, rand_num, app_id, group_array, result, ack_str);
}
void CenterThread::ackTakeGroupList(QString account, QString mac_str, int rand_num, u32 app_id, QJsonArray group_array, int result, QString ack_str)
{
QJsonObject root_obj;
QJsonDocument json_doc;
root_obj.insert("cmd_type", "group_list");
root_obj.insert("account", account);
root_obj.insert("app_id", (qint64)app_id);
root_obj.insert("group_list", group_array);
root_obj.insert("result", result);
root_obj.insert("ack_str", ack_str);
json_doc.setObject(root_obj);
QByteArray msg_ba = json_doc.toJson(QJsonDocument::Indented);
QString topic=makePubTopic(account, mac_str, rand_num, "group");
emit sigMqttPushMessage(topic, msg_ba);
}
最后,用户端收到解析并发送到前端显示分组名称:
cpp
if(cmd_type=="group_list")
{
QJsonArray group_array;
QJsonValue value=root_obj.value("group_list");
m_groupList.clear();
if(value.isArray())
{
group_array=value.toArray();
int nSize=group_array.size();
for(int i=0; i<nSize; i++)
{
QJsonValue value=group_array.at(i);
if(value.isObject())
{
GroupNodeStruct group_node;
QJsonObject group_obj=value.toObject();
if(group_obj.contains("group_name"))
{
QJsonValue value=group_obj.value("group_name");
if(value.isString())
{
group_node.groupName=value.toString();
}
}
if(group_obj.contains("dev_list"))//分组内的设备
{
QJsonValue value=group_obj.value("dev_list");
if(value.isArray())
{
QJsonArray dev_array=value.toArray();
int nSize=dev_array.size();
for(int i=0; i<nSize; i++)
{
QJsonValue value=dev_array.at(i);
if(value.isDouble())
{
u32 dev_sn=value.toDouble();
if(dev_sn>0)
{
group_node.devList.append(dev_sn);
}
}
}
}
}
if(!group_node.groupName.isEmpty())
{
int total_num=group_node.devList.size();
emit siqAddGroup(i, group_node.groupName, total_num);
m_groupList.append(group_node);
}
}
}
}
}
三、添加分组
用户后端请求添加分组代码:
cpp
void CenterMan::requestAddGroup(QString group_name)
{
QJsonObject root_obj;
QJsonDocument json_doc;
root_obj.insert("account", m_loginAccount);
root_obj.insert("rand_num", m_randNum);
root_obj.insert("mac", m_macStr);
root_obj.insert("app_id", (qint64)m_currAppWork.appID);
root_obj.insert("cmd_type", "add_group");
root_obj.insert("group_name", group_name);
json_doc.setObject(root_obj);
QByteArray msg_ba = json_doc.toJson(QJsonDocument::Indented);
QString topic=makePubTopic("group");
emit sigMqttPushMessage(topic, msg_ba);
}
服务器后台检查名称的合法性,如果重复了或者为空的都无法正常写入。
cpp
else if(cmd_type=="add_group")
{
QString group_name;
if(root_obj.contains("group_name"))
{
group_name=root_obj.value("group_name").toString();
}
if(group_name.isEmpty())
return;
GroupSqlite::GroupNodeStruct tag_group;
tag_groupSqlite.selectGroupNode(group_name, tag_group);
if(group_name==tag_group.groupName)
{
result=3;//已存在相同名称
ack_str="名称重复!";
}
else
{
ok=tag_groupSqlite.insertGroup(group_name);
if(ok)
{
result=0;//成功
ack_str="添加成功!";
}
else
{
result=4;//写入失败
ack_str="写入失败!";
}
}
ackAddGroup(account, mac_str, rand_num, app_id, group_name, result, ack_str);
}
void CenterThread::ackAddGroup(QString account, QString mac_str, int rand_num, u32 app_id, QString group_name, int result, QString ack_str)
{
QJsonObject root_obj;
QJsonDocument json_doc;
root_obj.insert("cmd_type", "add_group");
root_obj.insert("account", account);
root_obj.insert("app_id", (qint64)app_id);
root_obj.insert("group_name", group_name);
root_obj.insert("result", result);
root_obj.insert("ack_str", ack_str);
json_doc.setObject(root_obj);
QByteArray msg_ba = json_doc.toJson(QJsonDocument::Indented);
QString topic=makePubTopic(account, mac_str, rand_num, "group");
emit sigMqttPushMessage(topic, msg_ba);
}
用户端将新添加的分组发送到前端显示:
cpp
else if(cmd_type=="add_group")
{
QString group_name="";
if(root_obj.contains("group_name"))
{
QJsonValue value = root_obj.value("group_name");
group_name=value.toString();
}
if(group_name.isEmpty())
return;
if(result==0)
{
emit siqAddGroup(m_groupList.size(), group_name, 0);
GroupNodeStruct group_node;
group_node.groupName=group_name;
m_groupList.append(group_node);
}
}
四、重命名分组
用户后端请求重命名代码,输入参数是旧名称和新名称:
cpp
void CenterMan::requestRenameGroup(QString old_name, QString new_name)
{
QJsonObject root_obj;
QJsonDocument json_doc;
root_obj.insert("account", m_loginAccount);
root_obj.insert("rand_num", m_randNum);
root_obj.insert("mac", m_macStr);
root_obj.insert("app_id", (qint64)m_currAppWork.appID);
root_obj.insert("cmd_type", "rename_group");
root_obj.insert("old_name", old_name);
root_obj.insert("new_name", new_name);
json_doc.setObject(root_obj);
QByteArray msg_ba = json_doc.toJson(QJsonDocument::Indented);
QString topic=makePubTopic("group");
emit sigMqttPushMessage(topic, msg_ba);
}
服务器后台需要检查名称是否重复:
cpp
else if(cmd_type=="rename_group")
{
QString old_name;
if(root_obj.contains("old_name"))
{
old_name=root_obj.value("old_name").toString();
}
QString new_name;
if(root_obj.contains("new_name"))
{
new_name=root_obj.value("new_name").toString();
}
GroupSqlite::GroupNodeStruct tag_group;
tag_group.groupName="";
tag_groupSqlite.selectGroupNode(old_name, tag_group);
if(old_name==tag_group.groupName)
{
tag_group.groupName="";
tag_groupSqlite.selectGroupNode(new_name, tag_group);
if(new_name==tag_group.groupName)
{
result=4;//新名称已存在
ack_str="新名称已存在!";
}
else
{
tag_groupSqlite.updateGroupName(old_name, new_name);
tag_group.groupName="";
tag_groupSqlite.selectGroupNode(new_name, tag_group);
if(new_name==tag_group.groupName)
{
result=0;
ack_str="更新成功!";
}
else
{
result=5;//写入失败
ack_str="写入失败!";
}
}
}
else
{
result=3;//旧名称不存在
ack_str="旧名称不存在!";
}
ackUpdateGroupName(account, mac_str, rand_num, app_id, old_name, new_name, result,ack_str);
}
void CenterThread::ackUpdateGroupName(QString account, QString mac_str, int rand_num, u32 app_id, QString old_name, QString new_name, int result, QString ack_str)
{
QJsonObject root_obj;
QJsonDocument json_doc;
root_obj.insert("cmd_type", "rename_group");
root_obj.insert("account", account);
root_obj.insert("app_id", (qint64)app_id);
root_obj.insert("old_name", old_name);
root_obj.insert("new_name", new_name);
root_obj.insert("result", result);
root_obj.insert("ack_str", ack_str);
json_doc.setObject(root_obj);
QByteArray msg_ba = json_doc.toJson(QJsonDocument::Indented);
QString topic=makePubTopic(account, mac_str, rand_num, "group");
emit sigMqttPushMessage(topic, msg_ba);
}
用户后端收到返回后更新前端显示:
cpp
else if(cmd_type=="rename_group")
{
if(result==0)
{
QString old_name, new_name;
if(root_obj.contains("old_name"))
{
QJsonValue value = root_obj.value("old_name");
old_name=value.toString();
}
if(root_obj.contains("new_name"))
{
QJsonValue value = root_obj.value("new_name");
new_name=value.toString();
}
emit siqRenameGroup(old_name, new_name);
}
}
五、删除分组
用户后端请求删除分组代码:
cpp
void CenterMan::requestDelGroup(QString group_name)
{
QJsonObject root_obj;
QJsonDocument json_doc;
root_obj.insert("account", m_loginAccount);
root_obj.insert("rand_num", m_randNum);
root_obj.insert("mac", m_macStr);
root_obj.insert("app_id", (qint64)m_currAppWork.appID);
root_obj.insert("cmd_type", "del_group");
root_obj.insert("group_name", group_name);
json_doc.setObject(root_obj);
QByteArray msg_ba = json_doc.toJson(QJsonDocument::Indented);
QString topic=makePubTopic("group");
emit sigMqttPushMessage(topic, msg_ba);
}
平台收到后操作数据库进行删除,
cpp
else if(cmd_type=="del_group")
{
QString group_name;
if(root_obj.contains("group_name"))
{
group_name=root_obj.value("group_name").toString();
}
GroupSqlite::GroupNodeStruct tag_group;
tag_group.groupName="";
tag_groupSqlite.selectGroupNode(group_name, tag_group);
if(group_name!=tag_group.groupName)
{
result=3;//分组不存在
ack_str="分组不存在!";
}
else
{
tag_groupSqlite.delGroupNode(group_name);
tag_group.groupName="";
tag_groupSqlite.selectGroupNode(group_name, tag_group);
if(group_name!=tag_group.groupName)
{
result=0;//成功
ack_str="删除成功!";
}
else
{
result=4;//删除失败
ack_str="删除失败!";
}
}
ackDelGroup(account, mac_str, rand_num, app_id, group_name, result, ack_str);
}
void CenterThread::ackDelGroup(QString account, QString mac_str, int rand_num, u32 app_id, QString group_name, int result, QString ack_str)
{
QJsonObject root_obj;
QJsonDocument json_doc;
root_obj.insert("cmd_type", "del_group");
root_obj.insert("account", account);
root_obj.insert("app_id", (qint64)app_id);
root_obj.insert("group_name", group_name);
root_obj.insert("result", result);
root_obj.insert("ack_str", ack_str);
json_doc.setObject(root_obj);
QByteArray msg_ba = json_doc.toJson(QJsonDocument::Indented);
QString topic=makePubTopic(account, mac_str, rand_num, "group");
emit sigMqttPushMessage(topic, msg_ba);
}
用户端收到反馈后同步删除前端分组,
cpp
else if(cmd_type=="del_group")
{
QString group_name="";
if(root_obj.contains("group_name"))
{
QJsonValue value = root_obj.value("group_name");
group_name=value.toString();
}
if(result==0)
{
emit siqDelGroup(group_name);
int nSize=m_groupList.size();
for(int i=0; i<nSize; i++)
{
if(m_groupList.at(i).groupName==group_name)
{
m_groupList.removeAt(i);
break;
}
}
}
}
六、分组排序
排序的逻辑在文章开头时候说过了,用户端这边只需要按期望的顺序上传分组名称就行了,
cpp
void CenterMan::requestOrderGroup(QStringList group_list)
{
QJsonObject root_obj;
QJsonDocument json_doc;
root_obj.insert("account", m_loginAccount);
root_obj.insert("rand_num", m_randNum);
root_obj.insert("mac", m_macStr);
root_obj.insert("app_id", (qint64)m_currAppWork.appID);
root_obj.insert("cmd_type", "order_group");
QJsonArray group_array;
qDebug()<<"group_list="<<group_list;
for(auto iter : group_list)
{
group_array.append(iter);
}
root_obj.insert("group_list", group_array);
json_doc.setObject(root_obj);
QByteArray msg_ba = json_doc.toJson(QJsonDocument::Indented);
QString topic=makePubTopic("group");
emit sigMqttPushMessage(topic, msg_ba);
}
服务器后台按分组名称顺序一个个更新groupOrder值,这里的返回取巧了,直接返回了group_list的指令内容了,也就是分组列表。
cpp
else if(cmd_type=="order_group")
{
QJsonArray group_array;
if(root_obj.contains("group_list"))
{
group_array=root_obj.value("group_list").toArray();
}
int nSize=group_array.size();
for(int i=0; i<nSize; i++)
{
QString group_name=group_array.at(i).toString();
tag_groupSqlite.updateGroupOrder(group_name, i);
}
result=0;//成功
ack_str="排序成功!";
// ackOrderGroup(account, mac_str, rand_num, app_id, group_array, result, ack_str);
if(1)
{
QList<GroupSqlite::GroupNodeStruct>group_list;
QJsonArray group_array;
tag_groupSqlite.selectGroupList(group_list);
for(auto iter : group_list)
{
QJsonObject group_obj;
QJsonArray dev_list;
for(auto iter2 : iter.devList)
{
u32 dev_sn=iter2;
dev_list.append((qint64)dev_sn);
}
group_obj.insert("group_name", iter.groupName);
group_obj.insert("dev_list", dev_list);
group_array.append(group_obj);
}
ackTakeGroupList(account, mac_str, rand_num, app_id, group_array, result, ack_str);
}
}
用户端收到后整体上重新更新前端的分组页面。