|
|
#include "rescueload.h"
|
|
|
|
|
|
#include <QDateTime>
|
|
|
#include <QDir>
|
|
|
#include <QFile>
|
|
|
#include <QJsonArray>
|
|
|
#include <QJsonDocument>
|
|
|
#include <QJsonObject>
|
|
|
#include <QMessageBox>
|
|
|
|
|
|
// ==================== ImsiData数据类 start =======================
|
|
|
QHash<QString, QString> 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<int, QByteArray>)
|
|
|
// 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<QString, ImsiData> &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<int, QByteArray> 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<QString> &wnamelist, const QList<QString> &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=================================
|