#include "rescueload.h" #include #include #include #include #include #include #include // ==================== ImsiData数据类 start ======================= QHash ImsiData::operatorMap = { {"00", "移动"}, {"02", "移动"}, {"04", "移动"}, {"07", "移动"}, {"08", "移动"}, {"13", "移动"}, {"01", "联通"}, {"06", "联通"}, {"09", "联通"}, {"10", "联通"}, {"03", "电信"}, {"05", "电信"}, {"11", "电信"}, {"12", "电信"}, {"15", "广电"}, {"20","铁通"} }; ImsiData::ImsiData(const QJsonObject& json) { if (json.contains("latitude")) this->latitude = json.value("latitude").toString(); if (json.contains("longitude")) this->longitude = json.value("longitude").toString(); if (json.contains("altitude")) this->altitude = json.value("altitude").toInt(); if (json.contains("create_date")) // this->createDate = json.value("create_date").toString(); // 传过来的数据不准 this->createDate = QDateTime::currentDateTime().toString("yyyy-MM-ddThh:mm:ss"); if (json.contains("rssi")) this->rssi = json.value("rssi").toInt(); if (json.contains("fcn")) this->fcn = json.value("fcn").toString(); if (json.contains("imsi")) this->imsi = json.value("imsi").toString(); this->operatorName = getOperatorNameByImsi(this->imsi); // 第4、5位 } ImsiData::ImsiData(const ImsiData& from) { this->latitude = from.latitude; this->longitude = from.longitude; this->altitude = from.altitude; this->createDate = from.createDate; this->rssi = from.rssi; this->fcn = from.fcn; this->imsi = from.imsi; this->operatorName = from.operatorName; } QString ImsiData::getOperatorNameByImsi(QString imsi) { return operatorMap.value(imsi.mid(3,2)); } // ==================== ImsiData数据类 end ======================= // ===================== ImsiTableModel start ================================== ImsiTableModel::ImsiTableModel(QObject *parent) : QAbstractTableModel(parent) { // Set names to the role name hash container (QHash) // model.name, model.hue, model.saturation, model.brightness m_roleNames[imsiRole] = "imsi"; m_roleNames[latitudeRole] = "latitude"; m_roleNames[longitudeRole] = "longitude"; m_roleNames[dateRole] = "createDate"; m_roleNames[altitudeRole] = "altitude"; m_roleNames[rssiRole] = "rssi"; m_roleNames[fcnRole] = "fcn"; m_roleNames[operatorRole] = "operator"; m_horizontalHeader = {"IMSI", "运营商"}; m_defaultDir = QString("./搜救信息"); // 默认目录 // 检查并创建默认目录 QDir dir(m_defaultDir); if (!dir.exists()) { dir.mkpath("."); } } ImsiTableModel::~ImsiTableModel() { QString timeStr = QDateTime::currentDateTime().toString("yyyy-MM-ddThh-mm-ss"); QString defaultPath = QString("%1/搜救信息%2.csv").arg(getSaveDir(), timeStr); saveDataListToCsv(defaultPath); } QVariant ImsiTableModel::headerData(int section, Qt::Orientation orientation, int role) const { if(orientation == Qt::Horizontal) { //水平表头 if(Qt::DisplayRole == role && section < m_horizontalHeader.count()) { return m_horizontalHeader[section]; } } return QAbstractItemModel::headerData(section,orientation,role); } int ImsiTableModel::rowCount(const QModelIndex &parent) const { // For list models only the root node (an invalid parent) should return the list's size. For all // other (valid) parents, rowCount() should return 0 so that it does not become a tree model. Q_UNUSED(parent) return m_dataMap.count(); } int ImsiTableModel::columnCount(const QModelIndex &parent) const { Q_UNUSED(parent) return 2; } QVariant ImsiTableModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) return QVariant(); int column = index.column(); int row = index.row(); QString imsi = m_imsiList.at(row); ImsiData data = m_dataMap.value(imsi); switch (role) { case Qt::DisplayRole: if (column == 1) { return data.operatorName; } else if (column == 0) { return data.imsi; } break; // 对齐处理 case Qt::TextAlignmentRole: return Qt::AlignCenter; break; case imsiRole: return data.imsi; case latitudeRole: return data.latitude; case longitudeRole: return data.longitude; case dateRole: return data.createDate; case altitudeRole: return data.altitude; case rssiRole: return data.rssi; case fcnRole: return data.fcn; default: break; } return QVariant(); } QModelIndex ImsiTableModel::index(int row, int column, const QModelIndex &parent) const { if (parent.isValid() || row < 0 || column < 0 || row >= rowCount() || column >= columnCount()) return QModelIndex(); // Create and return a QModelIndex for the given row and column return createIndex(row, column); } void ImsiTableModel::setDataMap(const QHash &dataMap) { beginResetModel(); this->m_dataMap = dataMap; this->m_imsiList = dataMap.keys(); for (int i = 0; i < m_imsiList.size(); ++i) { m_imsiIndex.insert(m_imsiList[i], i); } endResetModel(); } void ImsiTableModel::clearData() { beginResetModel(); this->m_dataMap.clear(); this->m_imsiList.clear(); this->m_imsiIndex.clear(); endResetModel(); // endResetModel结束会自动发送resetModel信号,但不等价于clear,还需要另外判断,不如直接写一个单独的信号 emit dataCleared(); } void ImsiTableModel::updateData(const ImsiData &data) { QString imsi = data.imsi; if (m_dataMap.contains(imsi)) { // 更新现有数据 int row = m_imsiIndex.value(imsi); m_dataMap[imsi] = data; emit dataChanged(index(row, 0), index(row, columnCount() - 1), m_roleNames.keys()); } else { // 插入新数据 beginInsertRows(QModelIndex(), m_imsiList.size(), m_imsiList.size()); m_imsiList.append(imsi); m_dataMap.insert(imsi, data); m_imsiIndex.insert(imsi, m_imsiList.size()-1); endInsertRows(); } } int ImsiTableModel::getRole(QString rolename) { if (rolename == "latitude") return latitudeRole; else if (rolename == "longitude") return longitudeRole; else return -1; } QHash ImsiTableModel::roleNames() const { return m_roleNames; } void ImsiTableModel::saveDataListToCsv(const QString& filePath, const QString& delimiter) { QFile file(filePath); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { qWarning("Could not open file for writing."); return; } QTextStream out(&file); QStringList row; row << "IMSI" << "运营商" << "经度" << "纬度" << "海拔高度" << "频点" << "强度" << "记录时间"; // CSV header out << row.join(delimiter) << "\n"; for (const QString& imsi : m_imsiList) { row.clear(); ImsiData data = m_dataMap.value(imsi); row << data.imsi << data.operatorName << data.longitude << data.latitude << QString::number(data.altitude) << data.fcn << QString::number(data.rssi) << data.createDate; out << row.join(delimiter) << "\n"; } file.close(); } // ======================= ImsiTableModel end===================== // ======================= RescuLoad start=========================== RescueLoad::RescueLoad(QObject *parent) :QObject(parent), remoteIp("10.10.10.50"), remotePort(8056) { // remoteIp = "127.0.0.1"; } RescueLoad::~RescueLoad() {} void RescueLoad::startCommunication() { udpSocket = new QUdpSocket(this); connect(udpSocket, &QUdpSocket::readyRead, this, &RescueLoad::readData); } void RescueLoad::sendMessage(const QString &message) { QByteArray datagram = message.toUtf8(); sendMessage(datagram, QHostAddress(remoteIp), remotePort); } void RescueLoad::sendMessage(const QByteArray &datagram) { sendMessage(datagram, QHostAddress(remoteIp), remotePort); } void RescueLoad::sendMessage(const QByteArray &datagram, const QHostAddress& targetAddress, const int targetPort) { udpSocket->writeDatagram(datagram, targetAddress, targetPort); } void RescueLoad::readData() { while (udpSocket->hasPendingDatagrams()) { QByteArray datagram; datagram.resize(udpSocket->pendingDatagramSize()); QHostAddress sender; quint16 senderPort; udpSocket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort); // qDebug() << "Received response from" << sender.toString() << ":" << senderPort; // qDebug() << "Data:" << datagram; handleMessage(datagram, sender, senderPort); } } void RescueLoad::handleMessage(const QByteArray &datagram, const QHostAddress& sender, const int senderPort) { QJsonParseError json_error; QJsonDocument jsonDoc(QJsonDocument::fromJson(datagram, &json_error)); if(json_error.error != QJsonParseError::NoError || !jsonDoc.isObject()){ qDebug() << "[搜救] json error!"; return; } QJsonObject baseObj = jsonDoc.object(); QJsonValue vType = baseObj.value("type"); QJsonValue vMsg = baseObj.value("msg"); // if (!vType.isDouble() || !vMsg.isString()) return; int type = vType.toInt(); QString msg = vMsg.toString(); // if ("success" != msg) return; switch (type) { case 1: // 4G心跳包 // todo sendMessage(QString("{\"cmd\": \"heartbeat\"}").toUtf8(), sender, senderPort); // 定时回心跳,或者单独开定时器 break; case 2: // 5G心跳包 sendMessage(QString("{\"cmd\": \"heartbeat\"}").toUtf8(), sender, senderPort); break; case 3:{ // IMSI数据 QJsonArray array = baseObj.value("data").toArray(); for (int i = 0; i < array.size(); i++){ QJsonObject json = array.at(i).toObject(); ImsiData data(json); // ImsiData data; emit dataUpdate(data); } break; } default: break; } } void RescueLoad::syncTime() { QString timeStr = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"); QJsonObject timeObj; timeObj.insert("datetime", timeStr); QJsonObject sendObj; sendObj.insert("cmd", "syncTime"); sendObj.insert("params", timeObj); sendMessage(QJsonDocument(sendObj).toJson(QJsonDocument::Compact)); } /** * @brief RescueLoad::sendNameList 设置黑白名单 * @param action: 'reject'/'block'/'reject2lte'/'release2lte', #对其他imsi动作, * @param type: 'ADD'/'SUB'/'SAVE' #名单配置模式,ADD:增加名单,SUB:删除名单,SAVE:名单替换 * @param wnamelist: IMSI字符串列表 * @param bnamelist: IMSI字符串列表 */ void RescueLoad::sendNameList(const QString action, const QString type, const QList &wnamelist, const QList &bnamelist) { QJsonObject paramsObj; paramsObj.insert("action", action); paramsObj.insert("type", type); paramsObj.insert("wnamelist", QJsonArray::fromStringList(wnamelist)); paramsObj.insert("bnamelist", QJsonArray::fromStringList(bnamelist)); QJsonObject sendObj; sendObj.insert("cmd", "msg_set_namelist"); sendObj.insert("params", paramsObj); sendMessage(QJsonDocument(sendObj).toJson(QJsonDocument::Compact)); } // ============================ RescueLoad end=================================