#include "ParameterInspector.h" #include "ui_ParameterInspector.h" ParameterInspector::ParameterInspector(QWidget *parent) : QWidget(parent), ui(new Ui::ParameterInspector) { ui->setupUi(this); //检测文件夹,如果不存在,那么就新建一个,这里存着所有的qml文件 QDir *Dir = new QDir; if(!Dir->exists("./parameters")) Dir->mkdir("./params");//如果文件夹不存在就新建 setWindowTitle(tr("ParameterInspector")); // Set up the column headers for the message listing QStringList header; header << tr("Name"); header << tr("Value"); header << tr("Type"); ui->treeWidget->setHeaderLabels(header); ui->treeWidget->header()->resizeSection(0,400); ui->treeWidget->header()->resizeSection(1,150); ui->treeWidget->header()->resizeSection(2,50); ui->CancelpushButton->setEnabled(false); ui->pushButton_id->setEnabled(false); ui->pushButton_value->setEnabled(false); ui->WriteButton->setEnabled(false); TimerRunningFlag = true; flushTimer = new QTimer(this); connect(flushTimer,SIGNAL(timeout()), this,SLOT(mReflush())); flushTimer->start(50); } ParameterInspector::~ParameterInspector() { TimerRunningFlag = false; //clear 那些消息 delete ui; } void ParameterInspector::keyPressEvent(QKeyEvent *event) //键盘按下事件 { qDebug() << "keyPressEvent" << event; } void ParameterInspector::keyReleaseEvent(QKeyEvent *event) //键盘松开事件 { switch (event->key()) { case Qt::Key_Backspace: fineItem = fineItem.mid(0,fineItem.size() - 1); break; case Qt::Key_Delete: fineItem = fineItem.mid(0,fineItem.size() - 1); break; default: fineItem.append(event->text()); break; } qDebug() << fineItem; QTreeWidgetItemIterator I(ui->treeWidget); //while(*Item) if(*I) { QTreeWidgetItem *item = *I; if(!item->parent()) { qDebug() << "orphan" ; //找到最顶的项 QList childList = item->takeChildren(); for(QTreeWidgetItem * child:childList) { qDebug() << child->text(0); } } } //QTreeWidgetItem *item; //item = ui->treeWidget //parentItem = item->parent()->data(0,Qt::DisplayRole).toString(); //currentSelectType = param_gettype(item->data(2,Qt::DisplayRole)); //触发一次查询 } void ParameterInspector::mReflush() { if(isReflush == true) { isReflush = false; ui->progressBar->setValue(currentpersent); refreshView(); } } void ParameterInspector::resizeEvent(QResizeEvent * event) { Q_UNUSED(event); ui->treeWidget->header()->resizeSection(0,ui->treeWidget->width() * 0.5); ui->treeWidget->header()->resizeSection(1,ui->treeWidget->width() * 0.20); ui->treeWidget->header()->resizeSection(2,ui->treeWidget->width() * 0.20); } //添加一个设备, void ParameterInspector::addVehicles(int sysid, int compid) { Q_UNUSED(compid) if(!vehicles.keys().contains(sysid)) { //如果还没有这个设备,就添加一个 QMap param; vehicles.insert(sysid,param); ui->pushButton_system->setText(tr("Vehicle %1").arg(sysid)); //发送一次读取 uint8_t m_type = 0; emit ReadCmd(sysid,compid,m_type); } } //直接接受整个msg,这个函数传来的只有param_value这一帧,因此不需要识别 void ParameterInspector::appendParameter(mavlink_message_t msg) { //查找这个消息归属的设备和部件 if(!vehicles.keys().contains(msg.sysid)) { //如果还没有这个设备,就添加一个 QMap param; vehicles.insert(msg.sysid,param); } //解码 mavlink_param_value_t param_value;// mavlink_msg_param_value_decode(&msg,¶m_value); //如果当前是航点0,那么设置状态条 if(param_value.param_index == 0) { isNew = true; ui->progressBar->setMaximum(0); ui->progressBar->setMaximum(param_value.param_count - 1); } if(isNew) { currentpersent = param_value.param_index; } if(param_value.param_index == (param_value.param_count - 1)) { isNew = false; } //这里可能有bug,程序会死机 //ui->progressBar->setValue((int)param_value.param_index); //检查是否包含了该参数,如果没有,那么添加 QMap ParameterStorage; ParameterStorage = vehicles.value(msg.sysid); ParameterStorage.insert(param_value.param_index,param_value); vehicles.insert(msg.sysid,ParameterStorage); //需要刷新一次 isReflush = true; } void ParameterInspector::refreshView()//来一个参数更新一次 { QMap>::iterator ite; for(ite=vehicles.begin(); ite!=vehicles.end();++ite)//每一个key下面都是一个设备的所有参数 { //查找参数的index QMap params = ite.value();//得到所有参数item QMap::iterator param_ite; QMap widgetitems;//获取单独一个设备的参数显示条 widgetitems = uasParamTreeItems.value(ite.key()); for(param_ite=params.begin(); param_ite!=params.end();++param_ite)//历遍每一个参数 { mavlink_param_value_t param = param_ite.value();//每一个value QString paraName = param_id(param.param_id); //得到名称 //qDebug() << paraName;//ok //查找这个value是不是已经存,存在更新,不存在则建立 bool paramFound = false; foreach (QTreeWidgetItem* Item, widgetitems.values()) { if(Item->data(0,Qt::DisplayRole) == param_id(param.param_id)) { //这个设备已经存在 paramFound = true; //更新该参数 Item->setData(1,Qt::DisplayRole,param_value(param)); widgetitems.insert(param.param_index,Item); } } if(!paramFound)//没有找到 { //没有找到,新建一个组 QTreeWidgetItem* paraItem = new QTreeWidgetItem(); paraItem->setData(0,Qt::DisplayRole,param_id(param.param_id)); paraItem->setData(1,Qt::DisplayRole,param_value(param)); paraItem->setData(2,Qt::DisplayRole,param_type(param)); widgetitems.insert(param.param_index,paraItem); } } uasParamTreeItems.insert(ite.key(),widgetitems);//保存一整个设备的参数 //得到一个vehicle bool VehicleFound = false; foreach (QTreeWidgetItem* Item, uasTopLevelItems.values()) { if(Item->data(0,Qt::DisplayRole) == tr("Vehicle %1").arg(ite.key())) { //这个设备已经存在 VehicleFound = true; //存在测更新 Item->addChildren(uasParamTreeItems.value(ite.key()).values()); uasTopLevelItems.insert(ite.key(),Item); } } if(!VehicleFound)//没有找到 { //没有找到,新建一个组 QTreeWidgetItem* TopItem = new QTreeWidgetItem(); TopItem->setData(0,Qt::DisplayRole,tr("Vehicle %1").arg(ite.key())); TopItem->addChildren(uasParamTreeItems.value(ite.key()).values()); uasTopLevelItems.insert(ite.key(),TopItem); } ui->treeWidget->addTopLevelItems(uasTopLevelItems.values()); ui->treeWidget->expandAll(); if(isNew) { ui->treeWidget->scrollToBottom(); } } } void ParameterInspector::clearview(void) { QMap>::iterator ite; for (ite=uasParamTreeItems.begin(); ite!=uasParamTreeItems.end();++ite) { QMap param_ite = ite.value(); QList groupKeys = param_ite.uniqueKeys(); QList::iterator listKeys; for (listKeys=groupKeys.begin();listKeys!=groupKeys.end();++listKeys) { delete param_ite.take(*listKeys); } } uasParamTreeItems.clear(); QMap::iterator iteTree; for(iteTree=uasTopLevelItems.begin(); iteTree!=uasTopLevelItems.end();++iteTree) { delete iteTree.value(); iteTree.value() = NULL; } uasTopLevelItems.clear(); QMap>::iterator vehicle_ite;//删除这个 for (vehicle_ite=vehicles.begin(); vehicle_ite!=vehicles.end();++vehicle_ite) { vehicle_ite.value().clear(); //delete vehicle_ite.value(); //vehicle_ite.value() = NULL; } vehicles.clear(); ui->treeWidget->clear(); } QVariant ParameterInspector::param_value(mavlink_param_value_t param) { QVariant value; switch (param.param_type) { case MAV_PARAM_TYPE_UINT8: { value = ((uint8_t *)¶m.param_value)[0]; }break; case MAV_PARAM_TYPE_INT8: { value = ((int8_t *)¶m.param_value)[0]; }break; case MAV_PARAM_TYPE_UINT16: { value = ((uint16_t *)¶m.param_value)[0]; }break; case MAV_PARAM_TYPE_INT16: { value = ((int16_t *)¶m.param_value)[0]; }break; case MAV_PARAM_TYPE_UINT32: { value = ((uint32_t *)¶m.param_value)[0]; }break; case MAV_PARAM_TYPE_INT32: { value = ((int32_t *)¶m.param_value)[0]; }break; case MAV_PARAM_TYPE_UINT64: { #ifdef unix //value = ((ulong *)¶m.param_value)[0]; #else value = ((uint64_t *)¶m.param_value)[0]; #endif }break; case MAV_PARAM_TYPE_INT64: { #ifdef unix //value = ((long *)¶m.param_value)[0]; #else value = ((int64_t *)¶m.param_value)[0]; #endif }break; case MAV_PARAM_TYPE_REAL32: { value = ((float *)¶m.param_value)[0]; }break; case MAV_PARAM_TYPE_REAL64: { value = ((double *)¶m.param_value)[0]; }break; default: { value = ((float *)¶m.param_value)[0]; //qDebug() << "Unsupported type " << param.param_type; }break; } return value; } float ParameterInspector::param_getvalue(QVariant param,uint8_t type) { float value; union { uint8_t u8[8]; int8_t i8[8]; uint16_t u16[4]; int16_t i16[4]; uint32_t u32[2]; int32_t i32[2]; uint64_t u64; int64_t i64; float f[2]; double d; }src; switch (type) { case MAV_PARAM_TYPE_UINT8: { src.u8[0] = param.toUInt(); ((uint8_t *)&value)[0] = src.u8[0]; }break; case MAV_PARAM_TYPE_INT8: { src.i8[0] = param.toUInt(); ((int8_t *)&value)[0] = src.i8[0]; }break; case MAV_PARAM_TYPE_UINT16: { src.u16[0] = param.toUInt(); ((uint16_t *)&value)[0] = src.u16[0]; }break; case MAV_PARAM_TYPE_INT16: { src.i16[0] = param.toUInt(); ((int16_t *)&value)[0] = src.i16[0]; }break; case MAV_PARAM_TYPE_UINT32: { src.u32[0] = param.toUInt(); ((uint32_t *)&value)[0] = (uint32_t)src.u32[0]; }break; case MAV_PARAM_TYPE_INT32: { src.i32[0] = param.toUInt(); ((int32_t *)&value)[0] = (int32_t)src.i32[0]; }break; case MAV_PARAM_TYPE_UINT64: { src.u64 = param.toUInt(); ((uint64_t *)&value)[0] = (uint64_t )src.u64; }break; case MAV_PARAM_TYPE_INT64: { src.i64 = param.toUInt(); ((int64_t *)&value)[0] = (int64_t)src.i64; }break; case MAV_PARAM_TYPE_REAL32: { src.f[0] = param.toFloat(); ((float *)&value)[0] = (float)src.f[0]; }break; case MAV_PARAM_TYPE_REAL64: { src.d = param.toDouble(); ((double *)&value)[0]= (double)src.d; }break; default: { src.f[0] = param.toFloat(); ((float *)&value)[0] = (float)src.i32[0]; }break; } return value; } QVariant ParameterInspector::param_type(mavlink_param_value_t param) { QVariant value; switch (param.param_type) { case MAV_PARAM_TYPE_UINT8: { value = "uint8"; }break; case MAV_PARAM_TYPE_INT8: { value = "int8"; }break; case MAV_PARAM_TYPE_UINT16: { value = "uint16"; }break; case MAV_PARAM_TYPE_INT16: { value = "int16"; }break; case MAV_PARAM_TYPE_UINT32: { value = "uint32"; }break; case MAV_PARAM_TYPE_INT32: { value = "int32"; }break; case MAV_PARAM_TYPE_UINT64: { value = "uint64"; }break; case MAV_PARAM_TYPE_INT64: { value = "int64"; }break; case MAV_PARAM_TYPE_REAL32: { value = "float"; }break; case MAV_PARAM_TYPE_REAL64: { value = "double"; }break; default: { value = "unknow"; }break; } return value; } uint8_t ParameterInspector::param_gettype(QVariant type) { uint8_t value; if(type.toString() == "uint8") { value = MAV_PARAM_TYPE_UINT8; } else if(type.toString() == "int8") { value = MAV_PARAM_TYPE_INT8; } else if(type.toString() == "uint16") { value = MAV_PARAM_TYPE_UINT16; } else if(type.toString() == "int16") { value = MAV_PARAM_TYPE_INT16; } else if(type.toString() == "uint32") { value = MAV_PARAM_TYPE_UINT32; } else if(type.toString() == "int32") { value = MAV_PARAM_TYPE_INT32; } else if(type.toString() == "uint64") { value = MAV_PARAM_TYPE_UINT64; } else if(type.toString() == "int64") { value = MAV_PARAM_TYPE_INT64; } else if(type.toString() == "float") { value = MAV_PARAM_TYPE_REAL32; } else if(type.toString() == "double") { value = MAV_PARAM_TYPE_REAL64; } else if(type.toString() == "unknow") { value = 0; } return value; } //使用QString char* ParameterInspector::param_id(char *id)//设置id,如果id小于16,那么能够找到/0,如果等于或者大于,那么会找不到,因此乱码 { //char str[17]; uint8_t len = 0; while(len < 16) { if(id[len] != '\0') { //continue; } else { return id; } len++; } id[16] = '\0'; return id; } void ParameterInspector::setsystem(QVariant vehicle) { qDebug() << "set vehicle" << vehicle; ui->pushButton_system->setText(vehicle.toString()); } void ParameterInspector::on_pushButton_system_clicked() { if(!ui->pushButton_system->text().isEmpty()) { Selector *selector = new Selector(this); selector->setGeometry(0,0,this->width(),this->height()); QStringList list; list.clear(); QMap>::iterator ite; for(ite=vehicles.begin(); ite!=vehicles.end();++ite)//每一个key下面都是一个设备的所有参数 { list.append(tr("Vehicle %1").arg(ite.key())); } selector->setList(list,ui->pushButton_system->text()); connect(selector,SIGNAL(confirmValue(QVariant)), this,SLOT(setsystem(QVariant))); selector->show(); } } void ParameterInspector::setvalue(QVariant value) { ui->pushButton_value->setText(value.toString()); } void ParameterInspector::on_pushButton_value_clicked() { Inputter *inputter = new Inputter(this); inputter->setGeometry(0,0,this->width(),this->height()); inputter->setInitValue(ui->pushButton_value->text()); connect(inputter,SIGNAL(confirmValue(QVariant)), this,SLOT(setvalue(QVariant))); inputter->show(); } void ParameterInspector::on_ReadButton_clicked() { uint8_t m_sysid = 0; uint8_t m_compid = 1; uint8_t m_type = 0; QString systemStr = ui->pushButton_system->text(); int index = systemStr.indexOf(' '); QString selectid = ui->pushButton_system->text().mid(index); m_sysid = selectid.toInt(); emit ReadCmd(m_sysid,m_compid,m_type); } QVariant ParameterInspector::getParameter(QVariant id) { QVariant value; return value; } void ParameterInspector::on_treeWidget_itemDoubleClicked(QTreeWidgetItem *item, int column) { if(item->parent())//不是根节点才可以把数据写入框内 { ui->CancelpushButton->setEnabled(true); ui->pushButton_id->setEnabled(true); ui->pushButton_value->setEnabled(true); ui->WriteButton->setEnabled(true); ui->pushButton_id->setText(item->data(0,Qt::DisplayRole).toString()); ui->pushButton_value->setText(QString::number(item->data(1,Qt::DisplayRole).toFloat())); parentItem = item->parent()->data(0,Qt::DisplayRole).toString(); currentSelectType = param_gettype(item->data(2,Qt::DisplayRole)); } } void ParameterInspector::on_clearButton_clicked() { //清除所有的存储数据,包括显示 clearview(); //vehicles.clear(); } void ParameterInspector::on_WriteButton_clicked() { QString systemStr = parentItem; int index = systemStr.indexOf(' '); QString parentid = parentItem.mid(index); uint8_t sysid = parentid.toInt(); float value = param_getvalue(ui->pushButton_value->text().toFloat(),currentSelectType); emit WriteCmd(sysid,1,ui->pushButton_id->text().toLatin1().data(),currentSelectType,value); //读取是哪设备,是哪个参数,然后发送出去 } void ParameterInspector::on_CancelpushButton_clicked() { ui->pushButton_id->setText(tr("")); ui->pushButton_value->setText(tr("")); ui->CancelpushButton->setEnabled(false); ui->pushButton_id->setEnabled(false); ui->pushButton_value->setEnabled(false); ui->WriteButton->setEnabled(false); } void ParameterInspector::on_pushButton_Save_clicked() { QDateTime Time = QDateTime::currentDateTime(); QString Vehicle = ui->pushButton_system->text(); //读取当前的参数,并且保存到文件 QFileDialog *dlg = new QFileDialog(this); QString fileName = dlg->getSaveFileName(this, tr("Save Parameter File..."), QString("./params/%1%2").arg(Vehicle).arg(Time.toString("yyyyMMddHHmmss")), tr("parameters file (*.params)")); if(!fileName.isEmpty()) { ParamsEncode(fileName); } } void ParameterInspector::on_pushButton_Load_clicked() { //载入参数,跟当前飞机内参数对比,不一样的就修改 QFileDialog *dlg = new QFileDialog(this); QString fileName = dlg->getOpenFileName(this, tr("Selete Parameter File..."), "./params/", tr("parameters file (*.params)")); if(!fileName.isEmpty()) { ParamsDecode(fileName); } } void ParameterInspector::ParamsEncode(QString fileName) { QString Vehicle_Id; QByteArray ParamsString; ParamsString.append("# Onboard parameters for Vehicle %1\r\n"); ParamsString.append("#\r\n"); ParamsString.append("# Stack: MAVLink 通用\r\n"); ParamsString.append("# Vehicle: VTOL\r\n"); ParamsString.append("# Version: 1.4.1 dev\r\n"); ParamsString.append("# Git Revision: \r\n"); ParamsString.append("#\r\n"); ParamsString.append("# Vehicle-Id Component-Id Name Value Type\r\n"); //读取当前按键的设备号 QTreeWidgetItem * p; int Count = ui->treeWidget->topLevelItemCount(); qDebug() << Count; for(int i = 0;i < Count; i++) { if(ui->treeWidget->topLevelItem(i)->text(0) == ui->pushButton_system->text()) { p = ui->treeWidget->topLevelItem(i); //break; } qDebug() << i << Count; } //读取参数 int childCount = p->childCount(); for (int i = 0; i < childCount; i++) { QTreeWidgetItem *childItem = p->child(i); qDebug() << childItem->text(0) << childItem->text(1); ParamsString.append("1\t"); ParamsString.append("1\t"); ParamsString.append(childItem->text(0) + "\t"); ParamsString.append(childItem->text(1) + "\t"); ParamsString.append(QString::number(param_gettype(childItem->data(2,Qt::DisplayRole)),'f',0) + "\r\n"); } //文件读写 QFile file(fileName); if(!file.open(QIODevice::ReadWrite|QFile::Truncate)) { qDebug() << "File open error"; } file.write(ParamsString); file.close(); } void ParameterInspector::ParamsDecode(QString fileName) { QString systemStr = parentItem; int index = systemStr.indexOf(' '); QString parentid = parentItem.mid(index); uint8_t sysid = parentid.toInt(); QByteArray ParamsString; //文件读写 QFile file(fileName); if(!file.open(QIODevice::ReadWrite| QIODevice::Text)) { qDebug() << "File open error"; } ParamsString = file.readAll(); file.close(); //参数解析 //解析每一行 QByteArrayList LineList = ParamsString.split('\n'); for(QByteArray item:LineList) { if(item.at(0) == '#') { LineList.removeAt(LineList.indexOf(item)); continue; } else { break; } } for(QByteArray item:LineList) { QByteArrayList ItemList = item.split('\t'); //问题为ItemList 没有数据导致指针出现问题 if(ItemList.size() < 5) { qDebug() << ItemList.size(); break; } mavlink_message_t msg; //解码 mavlink_param_value_t param_value;// char *id = ItemList[2].data(); memcpy(param_value.param_id,param_id(id),16); //param_value.param_id = param_id(id); param_value.param_count = LineList.size(); param_value.param_index = LineList.indexOf(item); param_value.param_type = ItemList.at(4).toInt(); param_value.param_value = param_getvalue(ItemList.at(3).toFloat(),param_value.param_type); mavlink_msg_param_value_encode(ItemList.at(0).toInt(),ItemList.at(1).toInt(),&msg,¶m_value); appendParameter(msg); qDebug() << param_value.param_id << param_value.param_count << param_value.param_index << param_value.param_type << ItemList.at(3) << ItemList.size() << ItemList[2].size(); } }