add codes
This commit is contained in:
parent
7f4db7efdb
commit
fe60964e28
@ -72,67 +72,6 @@ void MyTcpClient::onConnected() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MyTcpClient::onReadyRead() {
|
void MyTcpClient::onReadyRead() {
|
||||||
// while (socket->bytesAvailable() > 0) {
|
|
||||||
// if (m_waitingForHeader) {
|
|
||||||
// // 1. 先尝试读取头部(固定长度)
|
|
||||||
// if (socket->bytesAvailable() < 4) {
|
|
||||||
// continue; // 数据不够,等待下次触发
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // 读取头部
|
|
||||||
// socket->read(reinterpret_cast<char*>(&header), 4);
|
|
||||||
|
|
||||||
// // 验证头部标识(0xAA55AA)
|
|
||||||
// if (header[0] != 0xAA ||
|
|
||||||
// header[1] != 0x55 ||
|
|
||||||
// header[2] != 0xAA) {
|
|
||||||
// qWarning() << "Invalid header! Disconnecting...";
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// char temp[10]={0};
|
|
||||||
// if(header[3] == kDownloadConfigFile){
|
|
||||||
|
|
||||||
// socket->read(reinterpret_cast<char*>(&temp), 6);
|
|
||||||
// memcpy((char*)&packge_len,temp + 2, 4);
|
|
||||||
// }else{
|
|
||||||
// QByteArray remain_data = socket->readAll();
|
|
||||||
// m_buffer.clear();
|
|
||||||
// m_buffer.append(reinterpret_cast<char*>(&header), 4); // 先存头部
|
|
||||||
// m_buffer.append(remain_data);
|
|
||||||
// emit dataReceived(m_buffer);
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // 进入等待数据状态
|
|
||||||
// m_waitingForHeader = false;
|
|
||||||
// m_buffer.clear();
|
|
||||||
// m_buffer.append(reinterpret_cast<char*>(&header), 4); // 先存头部
|
|
||||||
// m_buffer.append(reinterpret_cast<char*>(&temp), 6); // 先存头部
|
|
||||||
// } else {
|
|
||||||
// // 2. 根据头部的 len 读取剩余数据
|
|
||||||
// qint64 remainingBytes = packge_len - (m_buffer.size() - 10);
|
|
||||||
|
|
||||||
// if (remainingBytes <= 0) {
|
|
||||||
// // 数据已经完整,触发信号
|
|
||||||
// emit dataReceived(m_buffer);
|
|
||||||
// m_waitingForHeader = true; // 重置状态,准备接收下一个包
|
|
||||||
// break; // 继续处理缓冲区可能的下一个包
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // 读取剩余数据(不超过 remainingBytes)
|
|
||||||
// QByteArray newData = socket->read(remainingBytes);
|
|
||||||
// qDebug() << "Read" << newData.size() << "bytes";
|
|
||||||
// m_buffer.append(newData);
|
|
||||||
|
|
||||||
// // 检查是否已经读完
|
|
||||||
// if (m_buffer.size() - 10 >= packge_len) {
|
|
||||||
// qDebug() << "m_buffer" << m_buffer.size() << "bytes";
|
|
||||||
// emit dataReceived(m_buffer);
|
|
||||||
// m_waitingForHeader = true; // 准备接收下一个包
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
m_buffer.append(socket->readAll());
|
m_buffer.append(socket->readAll());
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
@ -153,7 +92,7 @@ void MyTcpClient::onReadyRead() {
|
|||||||
const LargeHeaderExtra *extra = reinterpret_cast<const LargeHeaderExtra *>(
|
const LargeHeaderExtra *extra = reinterpret_cast<const LargeHeaderExtra *>(
|
||||||
m_buffer.constData() + sizeof(BaseHeader));
|
m_buffer.constData() + sizeof(BaseHeader));
|
||||||
int payloadLen = extra->len;
|
int payloadLen = extra->len;
|
||||||
if (payloadLen <= 0 || payloadLen > 1024 * 1024) {
|
if (payloadLen <= 0 || payloadLen > 10 * 1024 * 1024) {
|
||||||
qWarning() << "Detected abnormal payload length:" << payloadLen;
|
qWarning() << "Detected abnormal payload length:" << payloadLen;
|
||||||
m_buffer.remove(0, sizeof(BaseHeader)); // 丢弃当前包头
|
m_buffer.remove(0, sizeof(BaseHeader)); // 丢弃当前包头
|
||||||
continue;
|
continue;
|
||||||
@ -161,8 +100,22 @@ void MyTcpClient::onReadyRead() {
|
|||||||
int totalLen = sizeof(BaseHeader) + sizeof(LargeHeaderExtra) + extra->len;
|
int totalLen = sizeof(BaseHeader) + sizeof(LargeHeaderExtra) + extra->len;
|
||||||
if (m_buffer.size() < totalLen)
|
if (m_buffer.size() < totalLen)
|
||||||
return; // 等待完整数据到达
|
return; // 等待完整数据到达
|
||||||
|
emit dataReceived( m_buffer);
|
||||||
|
m_buffer.remove(0, totalLen);
|
||||||
|
}else if(cmd == kGetLogInfo){
|
||||||
|
if (m_buffer.size() < sizeof(GetSubCardLogRsp))
|
||||||
|
return; // 等待更多数据
|
||||||
|
|
||||||
QByteArray payload = m_buffer.mid(sizeof(BaseHeader) + sizeof(LargeHeaderExtra), extra->len);
|
const GetSubCardLogRsp *extra = reinterpret_cast<const GetSubCardLogRsp *>(m_buffer.constData());
|
||||||
|
int payloadLen = extra->len;
|
||||||
|
if (payloadLen <= 0 || payloadLen > 10 * 1024 * 1024) {
|
||||||
|
qWarning() << "Detected abnormal payload length:" << payloadLen;
|
||||||
|
m_buffer.remove(0, sizeof(BaseHeader)); // 丢弃当前包头
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int totalLen = sizeof(GetSubCardLogRsp) + extra->len;
|
||||||
|
if (m_buffer.size() < totalLen)
|
||||||
|
return; // 等待完整数据到达
|
||||||
emit dataReceived( m_buffer);
|
emit dataReceived( m_buffer);
|
||||||
m_buffer.remove(0, totalLen);
|
m_buffer.remove(0, totalLen);
|
||||||
} else {
|
} else {
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
#include <QRegularExpressionValidator>
|
#include <QRegularExpressionValidator>
|
||||||
#include "data_config.h"
|
#include "data_config.h"
|
||||||
|
#include <QSettings>
|
||||||
|
|
||||||
Connect::Connect(QWidget *parent) :
|
Connect::Connect(QWidget *parent) :
|
||||||
QWidget(parent),
|
QWidget(parent),
|
||||||
@ -26,6 +27,9 @@ void Connect::on_pushButton_connect_clicked()
|
|||||||
m_tcpClient = MyTcpClient::instance();
|
m_tcpClient = MyTcpClient::instance();
|
||||||
// 连接服务器
|
// 连接服务器
|
||||||
m_tcpClient->connectToServer(g_strServerIp, 10000);
|
m_tcpClient->connectToServer(g_strServerIp, 10000);
|
||||||
|
QSettings *settings = new QSettings(QCoreApplication::applicationDirPath() + "/config/config.ini", QSettings::IniFormat);
|
||||||
|
settings->setValue("Server/IP", ui->lineEdit_IP->text());
|
||||||
|
|
||||||
this->close();
|
this->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ typedef unsigned char uint8_t;
|
|||||||
typedef unsigned short uint16_t;
|
typedef unsigned short uint16_t;
|
||||||
|
|
||||||
extern QString g_strServerIp; // 服务端IP
|
extern QString g_strServerIp; // 服务端IP
|
||||||
|
extern QString g_version;
|
||||||
|
|
||||||
#define SLOT_NUM 15
|
#define SLOT_NUM 15
|
||||||
#define CHANNEL_COUNT 4
|
#define CHANNEL_COUNT 4
|
||||||
@ -78,6 +79,10 @@ enum CMTCommand {
|
|||||||
kRebootCard = 21, // 重启板卡
|
kRebootCard = 21, // 重启板卡
|
||||||
kGetCardDcValue = 22, // 获取子板平均值
|
kGetCardDcValue = 22, // 获取子板平均值
|
||||||
kGetRelayStatus = 23, // 获取继电器状态
|
kGetRelayStatus = 23, // 获取继电器状态
|
||||||
|
KConfigProgress = 25,
|
||||||
|
kTimingCmd = 26,
|
||||||
|
kGetTimeInfo = 27,
|
||||||
|
kGetLogInfo = 28
|
||||||
};
|
};
|
||||||
enum RS485Baudrate {
|
enum RS485Baudrate {
|
||||||
kBaudrate2400 = 0,
|
kBaudrate2400 = 0,
|
||||||
@ -367,6 +372,13 @@ typedef struct {
|
|||||||
char data[0];
|
char data[0];
|
||||||
} UploadConfigReq;
|
} UploadConfigReq;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t head[3]; // 固定值:0xAA55AA
|
||||||
|
uint8_t cmd;
|
||||||
|
uint8_t version; // 版本号,默认为1
|
||||||
|
uint8_t code;
|
||||||
|
} UploadConfigRsp;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t head[3]; // 固定值:0xAA55AA
|
uint8_t head[3]; // 固定值:0xAA55AA
|
||||||
uint8_t cmd;
|
uint8_t cmd;
|
||||||
@ -393,7 +405,7 @@ typedef struct {
|
|||||||
char data[0];
|
char data[0];
|
||||||
} DownloadConfigRsp;
|
} DownloadConfigRsp;
|
||||||
|
|
||||||
// kConfigSubCard
|
// kConfigSubCard = 16
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t head[3]; // 固定值:0xAA55AA
|
uint8_t head[3]; // 固定值:0xAA55AA
|
||||||
uint8_t cmd;
|
uint8_t cmd;
|
||||||
@ -401,6 +413,14 @@ typedef struct {
|
|||||||
uint8_t card_id;
|
uint8_t card_id;
|
||||||
} ConfigSubCardReq;
|
} ConfigSubCardReq;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t head[3]; // 固定值:0xAA55AA
|
||||||
|
uint8_t cmd;
|
||||||
|
uint8_t version; // 版本号,默认为1
|
||||||
|
uint8_t card_id;
|
||||||
|
uint8_t code; // 0: 成功 1: 没有配置文件
|
||||||
|
} ConfigSubCardRsp;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t head[3]; // 固定值:0xAA55AA
|
uint8_t head[3]; // 固定值:0xAA55AA
|
||||||
uint8_t cmd;
|
uint8_t cmd;
|
||||||
@ -471,6 +491,54 @@ typedef struct {
|
|||||||
uint8_t code;
|
uint8_t code;
|
||||||
} ConfigMacRsp;
|
} ConfigMacRsp;
|
||||||
|
|
||||||
|
// kGetLogInfo = 28
|
||||||
|
typedef struct {
|
||||||
|
uint8_t head[3]; // 固定值:0xAA55AA
|
||||||
|
uint8_t cmd;
|
||||||
|
uint8_t version; // 版本号,默认为1
|
||||||
|
uint8_t card_id;
|
||||||
|
uint8_t level;
|
||||||
|
} GetSubCardLogReq;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t head[3]; // 固定值:0xAA55AA
|
||||||
|
uint8_t cmd;
|
||||||
|
uint8_t version; // 版本号,默认为1
|
||||||
|
uint8_t card_id;
|
||||||
|
uint8_t code;
|
||||||
|
uint32_t len;
|
||||||
|
char data[0]; // 请保存为.tar.gz文件
|
||||||
|
} GetSubCardLogRsp;
|
||||||
|
|
||||||
|
// cmd: kTimingCmd = 26
|
||||||
|
typedef struct {
|
||||||
|
uint8_t head[3]; // 固定值:0xAA55AA
|
||||||
|
uint8_t cmd;
|
||||||
|
uint8_t version; // 版本号,默认为1
|
||||||
|
uint32_t ts; // 时间戳
|
||||||
|
} SetTimingReq;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t head[3]; // 固定值:0xAA55AA
|
||||||
|
uint8_t cmd;
|
||||||
|
uint8_t version; // 版本号,默认为1
|
||||||
|
uint8_t code; // 0: 成功 其它:失败
|
||||||
|
} SetTimingRsp;
|
||||||
|
|
||||||
|
// cmd: kGetTimeInfo = 27
|
||||||
|
typedef struct {
|
||||||
|
uint8_t head[3]; // 固定值:0xAA55AA
|
||||||
|
uint8_t cmd;
|
||||||
|
uint8_t version; // 版本号,默认为1
|
||||||
|
} GetTimeInfoReq;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t head[3]; // 固定值:0xAA55AA
|
||||||
|
uint8_t cmd;
|
||||||
|
uint8_t version; // 版本号,默认为1
|
||||||
|
uint32_t ts; // 时间戳
|
||||||
|
} GetTimeInfoRsp;
|
||||||
|
|
||||||
struct BaseHeader {
|
struct BaseHeader {
|
||||||
uint8_t head[3]; // 固定 0xAA 0x55 0xAA
|
uint8_t head[3]; // 固定 0xAA 0x55 0xAA
|
||||||
uint8_t cmd;
|
uint8_t cmd;
|
||||||
|
0
doc/ReadME.txt
Normal file
0
doc/ReadME.txt
Normal file
126
mainwindow.cpp
126
mainwindow.cpp
@ -26,8 +26,10 @@
|
|||||||
#include "pointname.h"
|
#include "pointname.h"
|
||||||
#include "ethconfig.h"
|
#include "ethconfig.h"
|
||||||
#include "macconfig.h"
|
#include "macconfig.h"
|
||||||
|
#include <QDateTime>
|
||||||
|
|
||||||
QString g_strServerIp;
|
QString g_strServerIp;
|
||||||
|
QString g_version;
|
||||||
|
|
||||||
MainWindow::MainWindow(QWidget *parent)
|
MainWindow::MainWindow(QWidget *parent)
|
||||||
: QMainWindow(parent)
|
: QMainWindow(parent)
|
||||||
@ -36,6 +38,7 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
// QMenuBar *menuBar = this->menuBar();
|
// QMenuBar *menuBar = this->menuBar();
|
||||||
// this->setMenuBar(menuBar); //添加到对象树
|
// this->setMenuBar(menuBar); //添加到对象树
|
||||||
// menuBar->addMenu(ui->menu_start);
|
// menuBar->addMenu(ui->menu_start);
|
||||||
|
g_version = "1.1";
|
||||||
current_slot = -1;
|
current_slot = -1;
|
||||||
tsi_config_file = "";
|
tsi_config_file = "";
|
||||||
ui->widget_body->setProperty("flag", "title");
|
ui->widget_body->setProperty("flag", "title");
|
||||||
@ -97,10 +100,12 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
QObject::connect(ui->action_disconnect, &QAction::triggered, this, &MainWindow::onDisconnect);
|
QObject::connect(ui->action_disconnect, &QAction::triggered, this, &MainWindow::onDisconnect);
|
||||||
QObject::connect(ui->action_eth, &QAction::triggered, this, &MainWindow::onEthConfig);
|
QObject::connect(ui->action_eth, &QAction::triggered, this, &MainWindow::onEthConfig);
|
||||||
QObject::connect(ui->action_mac, &QAction::triggered, this, &MainWindow::onMACConfig);
|
QObject::connect(ui->action_mac, &QAction::triggered, this, &MainWindow::onMACConfig);
|
||||||
|
QObject::connect(ui->action_time, &QAction::triggered, this, &MainWindow::onSetTime);
|
||||||
|
|
||||||
QSettings settingsread(QCoreApplication::applicationDirPath() + "\\config\\config.ini", QSettings::IniFormat);
|
QSettings settingsread(QCoreApplication::applicationDirPath() + "\\config\\config.ini", QSettings::IniFormat);
|
||||||
g_strServerIp = settingsread.value("Server/IP").toString();
|
g_strServerIp = settingsread.value("Server/IP").toString();
|
||||||
connectServer();
|
connectServer();
|
||||||
|
statusBar()->showMessage("未连接",10000);
|
||||||
// 设置自定义日志处理函数
|
// 设置自定义日志处理函数
|
||||||
#ifndef QT_DEBUG
|
#ifndef QT_DEBUG
|
||||||
//qInstallMessageHandler(messageHandler);
|
//qInstallMessageHandler(messageHandler);
|
||||||
@ -200,6 +205,8 @@ void MainWindow::createMenu(const QString &rootTitle, QPushButton *parent) {
|
|||||||
QAction *reset = mainMenu->addAction("重置模块");
|
QAction *reset = mainMenu->addAction("重置模块");
|
||||||
QAction *upgrade = mainMenu->addAction("升级固件");
|
QAction *upgrade = mainMenu->addAction("升级固件");
|
||||||
QAction *version = mainMenu->addAction("查看版本");
|
QAction *version = mainMenu->addAction("查看版本");
|
||||||
|
QAction *config_sub_card = mainMenu->addAction("更新配置");
|
||||||
|
QAction *get_sub_log = mainMenu->addAction("获取日志");
|
||||||
// 绑定 **鼠标事件过滤器**,确保只响应右键
|
// 绑定 **鼠标事件过滤器**,确保只响应右键
|
||||||
// 设置右键菜单策略
|
// 设置右键菜单策略
|
||||||
parent->setContextMenuPolicy(Qt::CustomContextMenu);
|
parent->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
@ -222,6 +229,8 @@ void MainWindow::createMenu(const QString &rootTitle, QPushButton *parent) {
|
|||||||
QObject::connect(reset, &QAction::triggered, this, &MainWindow::onMenuActionTriggered);
|
QObject::connect(reset, &QAction::triggered, this, &MainWindow::onMenuActionTriggered);
|
||||||
QObject::connect(upgrade, &QAction::triggered, this, &MainWindow::onMenuActionTriggered);
|
QObject::connect(upgrade, &QAction::triggered, this, &MainWindow::onMenuActionTriggered);
|
||||||
QObject::connect(version, &QAction::triggered, this, &MainWindow::onMenuActionTriggered);
|
QObject::connect(version, &QAction::triggered, this, &MainWindow::onMenuActionTriggered);
|
||||||
|
QObject::connect(config_sub_card, &QAction::triggered, this, &MainWindow::onMenuActionTriggered);
|
||||||
|
QObject::connect(get_sub_log, &QAction::triggered, this, &MainWindow::onMenuActionTriggered);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::createMenuSet(const QString &rootTitle, QPushButton *parent) {
|
void MainWindow::createMenuSet(const QString &rootTitle, QPushButton *parent) {
|
||||||
@ -271,7 +280,7 @@ void MainWindow::onMenuActionTriggered() {
|
|||||||
qDebug() << "rack_type" << action->data();
|
qDebug() << "rack_type" << action->data();
|
||||||
card_type = static_cast<CardType>(action->data().toInt());
|
card_type = static_cast<CardType>(action->data().toInt());
|
||||||
int button_id = button->objectName().right(button->objectName().length() - 15).toInt();
|
int button_id = button->objectName().right(button->objectName().length() - 15).toInt();
|
||||||
qDebug() << slot_type << rack_type << button_id << map_slot_config[button_id + 1].slot_type << map_slot_config[button_id + 2].slot_type ;
|
qDebug() << slot_type << rack_type << button_id << map_slot_config[button_id].slot_type << map_slot_config[button_id + 2].slot_type ;
|
||||||
map_slot_config[button_id].slot_label->setStyleSheet("QLabel { color :#2980b9; font: bold 16px}");
|
map_slot_config[button_id].slot_label->setStyleSheet("QLabel { color :#2980b9; font: bold 16px}");
|
||||||
QString chan_display = "";
|
QString chan_display = "";
|
||||||
if (slot_type == "DOM810") {
|
if (slot_type == "DOM810") {
|
||||||
@ -380,6 +389,10 @@ void MainWindow::onMenuActionTriggered() {
|
|||||||
sendUpgradePackage(button_id);
|
sendUpgradePackage(button_id);
|
||||||
} else if (action->text() == "查看版本") {
|
} else if (action->text() == "查看版本") {
|
||||||
getVersion(button_id);
|
getVersion(button_id);
|
||||||
|
}else if (action->text() == "更新配置") {
|
||||||
|
ConfigSubCard(button_id);
|
||||||
|
}else if (action->text() == "获取日志") {
|
||||||
|
ConfigSubCard(button_id);
|
||||||
}
|
}
|
||||||
break; // 找到按钮后,跳出循环
|
break; // 找到按钮后,跳出循环
|
||||||
}
|
}
|
||||||
@ -725,7 +738,38 @@ void MainWindow::getVersion(int slot) {
|
|||||||
m_tcpClient->waitForRead();
|
m_tcpClient->waitForRead();
|
||||||
qDebug() << "bytesWritten: " << bytesWritten;
|
qDebug() << "bytesWritten: " << bytesWritten;
|
||||||
}
|
}
|
||||||
|
void MainWindow::ConfigSubCard(int slot){
|
||||||
|
slot_no = slot;
|
||||||
|
qDebug() << "slot" << slot ;
|
||||||
|
ConfigSubCardReq config_sub_card_req = { {0xAA, 0x55, 0xAA}, kConfigSubCard, 1, 0 };
|
||||||
|
if (slot == 0) {
|
||||||
|
config_sub_card_req.card_id = 0xFF;
|
||||||
|
} else {
|
||||||
|
config_sub_card_req.card_id = slot & 0xFF;
|
||||||
|
}
|
||||||
|
char send_buf[20] = {0};
|
||||||
|
memcpy(send_buf, (char *)&config_sub_card_req, sizeof(ConfigSubCardReq));
|
||||||
|
int length = sizeof(ConfigSubCardReq);
|
||||||
|
qint64 bytesWritten = m_tcpClient->sendData(send_buf, length);
|
||||||
|
m_tcpClient->waitForRead();
|
||||||
|
qDebug() << "bytesWritten: " << bytesWritten;
|
||||||
|
}
|
||||||
|
void MainWindow::GetSubLog(int slot){
|
||||||
|
slot_no = slot;
|
||||||
|
qDebug() << "slot" << slot ;
|
||||||
|
GetSubCardLogReq get_sub_card_log_req = { {0xAA, 0x55, 0xAA}, kGetLogInfo, 1, 0 };
|
||||||
|
if (slot == 0) {
|
||||||
|
get_sub_card_log_req.card_id = 0xFF;
|
||||||
|
} else {
|
||||||
|
get_sub_card_log_req.card_id = slot & 0xFF;
|
||||||
|
}
|
||||||
|
char send_buf[20] = {0};
|
||||||
|
memcpy(send_buf, (char *)&get_sub_card_log_req, sizeof(GetSubCardLogReq));
|
||||||
|
int length = sizeof(GetSubCardLogReq);
|
||||||
|
qint64 bytesWritten = m_tcpClient->sendData(send_buf, length);
|
||||||
|
m_tcpClient->waitForRead();
|
||||||
|
qDebug() << "bytesWritten: " << bytesWritten;
|
||||||
|
}
|
||||||
void MainWindow::readData(const QByteArray &data) {
|
void MainWindow::readData(const QByteArray &data) {
|
||||||
qDebug() << "Received from server:" << data;
|
qDebug() << "Received from server:" << data;
|
||||||
|
|
||||||
@ -750,20 +794,72 @@ void MainWindow::readData(const QByteArray &data) {
|
|||||||
} else if(cmd == kDownloadConfigFile){
|
} else if(cmd == kDownloadConfigFile){
|
||||||
//qDebug() << "header.len" << header.len;
|
//qDebug() << "header.len" << header.len;
|
||||||
char *config_file = NULL;
|
char *config_file = NULL;
|
||||||
int len = data[4];
|
|
||||||
DownloadConfigRsp download_config;
|
DownloadConfigRsp download_config;
|
||||||
memcpy(&download_config,data,sizeof(DownloadConfigRsp));
|
memcpy(&download_config,data,sizeof(DownloadConfigRsp));
|
||||||
config_file = (char*)malloc(download_config.len + 1);
|
config_file = (char*)malloc(download_config.len + 1);
|
||||||
memset(config_file,0,download_config.len + 1);
|
memset(config_file,0,download_config.len + 1);
|
||||||
memcpy(config_file, data.data() + sizeof(DownloadConfigRsp), download_config.len);
|
memcpy(config_file, data.data() + sizeof(DownloadConfigRsp), download_config.len);
|
||||||
QString filename_ = QCoreApplication::applicationDirPath() + "\\config\\tsi_config_file_download.json";
|
QString filename_ = QCoreApplication::applicationDirPath() + "\\config\\tsi_config_file_download.json";
|
||||||
//qDebug() << config_file ;
|
|
||||||
QFile file(filename_);
|
QFile file(filename_);
|
||||||
file.open(QIODevice::WriteOnly);
|
file.open(QIODevice::WriteOnly);
|
||||||
file.write(config_file,download_config.len);
|
file.write(config_file,download_config.len);
|
||||||
file.close();
|
file.close();
|
||||||
if(config_file != NULL)
|
if(config_file != NULL)
|
||||||
free(config_file);
|
free(config_file);
|
||||||
|
statusBar()->showMessage("下载配置成功!", 3000);
|
||||||
|
}else if(cmd == kConfigSubCard){
|
||||||
|
ConfigSubCardRsp config_sub_card;
|
||||||
|
memcpy(&config_sub_card, data.data(), sizeof(ConfigSubCardRsp));
|
||||||
|
if(config_sub_card.code == 0){
|
||||||
|
statusBar()->showMessage("配置成功!", 3000);
|
||||||
|
}else if(config_sub_card.code == 1){
|
||||||
|
statusBar()->showMessage("没有配置文件!", 3000);
|
||||||
|
}
|
||||||
|
}else if(cmd == kGetLogInfo){
|
||||||
|
char *log_file = NULL;
|
||||||
|
GetSubCardLogRsp sub_card_log_rsp;
|
||||||
|
memcpy(&sub_card_log_rsp,data,sizeof(GetSubCardLogRsp));
|
||||||
|
log_file = (char*)malloc(sub_card_log_rsp.len + 1);
|
||||||
|
memset(log_file,0,sub_card_log_rsp.len + 1);
|
||||||
|
memcpy(log_file, data.data() + sizeof(GetSubCardLogRsp), sub_card_log_rsp.len);
|
||||||
|
QString file_name = QString("tsi_card_%1.tar.gz").arg(sub_card_log_rsp.card_id);
|
||||||
|
QString log_path = QCoreApplication::applicationDirPath() + "\\log\\" + file_name;
|
||||||
|
QFile file(log_path);
|
||||||
|
file.open(QIODevice::WriteOnly);
|
||||||
|
file.write(log_file,sub_card_log_rsp.len);
|
||||||
|
file.close();
|
||||||
|
if(log_file != NULL)
|
||||||
|
free(log_file);
|
||||||
|
}else if(cmd == kTimingCmd){
|
||||||
|
SetTimingRsp set_time_rsp;
|
||||||
|
memcpy(&set_time_rsp, data.data(), sizeof(SetTimingRsp));
|
||||||
|
if(set_time_rsp.code == 0){
|
||||||
|
statusBar()->showMessage("校时成功!", 3000);
|
||||||
|
}else if(set_time_rsp.code == 1){
|
||||||
|
statusBar()->showMessage("校时失败!", 3000);
|
||||||
|
}
|
||||||
|
}else if(cmd == kUploadConfigFile){
|
||||||
|
UploadConfigRsp upload_config_rsp;
|
||||||
|
memcpy(&upload_config_rsp, data.data(), sizeof(UploadConfigRsp));
|
||||||
|
if(upload_config_rsp.code == 0){
|
||||||
|
statusBar()->showMessage("上传成功!", 2000);
|
||||||
|
}else if(upload_config_rsp.code == 1){
|
||||||
|
statusBar()->showMessage("上传失败!", 2000);
|
||||||
|
}
|
||||||
|
}else if(cmd == KConfigProgress){
|
||||||
|
ConfigSubCardProgress config_sub_card_progress;
|
||||||
|
memcpy(&config_sub_card_progress, data.data(), sizeof(ConfigSubCardProgress));
|
||||||
|
QString status ;
|
||||||
|
if(config_sub_card_progress.code == 0 && config_sub_card_progress.stage == 1){
|
||||||
|
status = QString("板卡 %1 配置成功!").arg(config_sub_card_progress.subcard_id);
|
||||||
|
map_slot_config[config_sub_card_progress.subcard_id].slot_label->setStyleSheet("");
|
||||||
|
statusBar()->showMessage(status, 2000);
|
||||||
|
}
|
||||||
|
if(config_sub_card_progress.code == 1){
|
||||||
|
status = QString("板卡 %1 配置失败!").arg(config_sub_card_progress.subcard_id);
|
||||||
|
map_slot_config[config_sub_card_progress.subcard_id].slot_label->setStyleSheet("QLabel { color :#FF0000; font: bold 16px}");
|
||||||
|
statusBar()->showMessage(status, 2000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -795,9 +891,15 @@ void MainWindow::onMACConfig(){
|
|||||||
mac_config->setWindowModality(Qt::ApplicationModal);
|
mac_config->setWindowModality(Qt::ApplicationModal);
|
||||||
mac_config->show();
|
mac_config->show();
|
||||||
}
|
}
|
||||||
|
void MainWindow::onSetTime(){
|
||||||
void MainWindow::on_pushButton_upload_clicked()
|
SetTimingReq set_time_req = { {0xAA, 0x55, 0xAA}, kTimingCmd, 1,0 };
|
||||||
{
|
int length = sizeof(SetTimingReq);
|
||||||
|
set_time_req.ts = QDateTime::currentSecsSinceEpoch();
|
||||||
|
qint64 bytesWritten = m_tcpClient->sendData((char*)&set_time_req, length);
|
||||||
|
m_tcpClient->waitForRead();
|
||||||
|
qDebug() << "bytesWritten: " << bytesWritten;
|
||||||
|
}
|
||||||
|
void MainWindow::UploadConfigFile(uint8_t sub_cmd){
|
||||||
QMessageBox *box = new QMessageBox(QMessageBox::Question, "提示", "确认上传配置文件?", QMessageBox::Yes | QMessageBox::No, this);
|
QMessageBox *box = new QMessageBox(QMessageBox::Question, "提示", "确认上传配置文件?", QMessageBox::Yes | QMessageBox::No, this);
|
||||||
box->button(QMessageBox::Yes)->setText("确认");
|
box->button(QMessageBox::Yes)->setText("确认");
|
||||||
box->button(QMessageBox::No)->setText("取消");
|
box->button(QMessageBox::No)->setText("取消");
|
||||||
@ -824,7 +926,7 @@ void MainWindow::on_pushButton_upload_clicked()
|
|||||||
}
|
}
|
||||||
qDebug() << "fileSize" << fileSize ;
|
qDebug() << "fileSize" << fileSize ;
|
||||||
// 创建 PackageHead 结构体
|
// 创建 PackageHead 结构体
|
||||||
UploadConfigReq upload_config_req = { {0xAA, 0x55, 0xAA}, kUploadConfigFile,1, fileSize, 0, 0, {} };
|
UploadConfigReq upload_config_req = { {0xAA, 0x55, 0xAA}, kUploadConfigFile,1, fileSize, sub_cmd, 0, {} };
|
||||||
// 计算文件的 CRC 校验和
|
// 计算文件的 CRC 校验和
|
||||||
upload_config_req.crc = calculate_crc(0, fileData);
|
upload_config_req.crc = calculate_crc(0, fileData);
|
||||||
upload_config_req.len = fileSize;
|
upload_config_req.len = fileSize;
|
||||||
@ -859,4 +961,12 @@ void MainWindow::on_pushButton_upload_clicked()
|
|||||||
free(send_buf);
|
free(send_buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void MainWindow::on_pushButton_upload_clicked(){
|
||||||
|
UploadConfigFile(0x0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MainWindow::on_pushButton_upload_config_clicked(){
|
||||||
|
UploadConfigFile(0x1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -57,8 +57,11 @@ private:
|
|||||||
void readJsonFile(const QString &filePath);
|
void readJsonFile(const QString &filePath);
|
||||||
void sendUpgradePackage(int slot);
|
void sendUpgradePackage(int slot);
|
||||||
void getVersion(int slot);
|
void getVersion(int slot);
|
||||||
|
void ConfigSubCard(int slot);
|
||||||
|
void GetSubLog(int slot);
|
||||||
void initStyle();
|
void initStyle();
|
||||||
void connectServer();
|
void connectServer();
|
||||||
|
void UploadConfigFile(uint8_t sub_cmd);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
@ -72,6 +75,7 @@ private slots:
|
|||||||
void onDisconnect();
|
void onDisconnect();
|
||||||
void onEthConfig();
|
void onEthConfig();
|
||||||
void onMACConfig();
|
void onMACConfig();
|
||||||
|
void onSetTime();
|
||||||
|
|
||||||
void onMenuActionTriggered();
|
void onMenuActionTriggered();
|
||||||
void on_pushButton_slot_clicked();
|
void on_pushButton_slot_clicked();
|
||||||
@ -82,5 +86,6 @@ private slots:
|
|||||||
void on_pushButton_open_clicked();
|
void on_pushButton_open_clicked();
|
||||||
void on_pushButton_download_clicked();
|
void on_pushButton_download_clicked();
|
||||||
void on_pushButton_upload_clicked();
|
void on_pushButton_upload_clicked();
|
||||||
|
void on_pushButton_upload_config_clicked();
|
||||||
};
|
};
|
||||||
#endif // MAINWINDOW_H
|
#endif // MAINWINDOW_H
|
||||||
|
@ -68,6 +68,9 @@
|
|||||||
<height>45</height>
|
<height>45</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>保存配置</string>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>保存</string>
|
<string>保存</string>
|
||||||
</property>
|
</property>
|
||||||
@ -93,6 +96,9 @@
|
|||||||
<height>45</height>
|
<height>45</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>打开配置文件</string>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>打开</string>
|
<string>打开</string>
|
||||||
</property>
|
</property>
|
||||||
@ -118,6 +124,9 @@
|
|||||||
<height>45</height>
|
<height>45</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>上传配置文件</string>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>上传</string>
|
<string>上传</string>
|
||||||
</property>
|
</property>
|
||||||
@ -143,6 +152,9 @@
|
|||||||
<height>45</height>
|
<height>45</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>下载配置文件</string>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>下载</string>
|
<string>下载</string>
|
||||||
</property>
|
</property>
|
||||||
@ -168,8 +180,11 @@
|
|||||||
<height>45</height>
|
<height>45</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>上传配置文件并下发到子板卡</string>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>上传和配置</string>
|
<string>配置</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include "acceleration_ds.h"
|
#include "acceleration_ds.h"
|
||||||
#include "velocity_ds.h"
|
#include "velocity_ds.h"
|
||||||
#include <QListView>
|
#include <QListView>
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
Setpoint::Setpoint(int slot_no_,int cardtype,QWidget *parent) :
|
Setpoint::Setpoint(int slot_no_,int cardtype,QWidget *parent) :
|
||||||
QWidget(parent),
|
QWidget(parent),
|
||||||
@ -154,6 +155,11 @@ void Setpoint::update()
|
|||||||
std::shared_ptr<CardBase> base_ptr = ConfigMgr::Instance()->GetSlotPtr(slot_no);
|
std::shared_ptr<CardBase> base_ptr = ConfigMgr::Instance()->GetSlotPtr(slot_no);
|
||||||
std::shared_ptr<VibrationData> setpoint_data = std::dynamic_pointer_cast<VibrationData>(base_ptr);
|
std::shared_ptr<VibrationData> setpoint_data = std::dynamic_pointer_cast<VibrationData>(base_ptr);
|
||||||
std::vector<std::shared_ptr<VariableBase>> variable_ = setpoint_data->variables_;
|
std::vector<std::shared_ptr<VariableBase>> variable_ = setpoint_data->variables_;
|
||||||
|
if(variable_.size() <= 0 )
|
||||||
|
{
|
||||||
|
QMessageBox::information(this, QStringLiteral("提示"), "请先配置完通道参数!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
if(!variable_[chan]->x1_.checked){
|
if(!variable_[chan]->x1_.checked){
|
||||||
ui->checkBox_1x_ampl->setEnabled(false);
|
ui->checkBox_1x_ampl->setEnabled(false);
|
||||||
ui->lineEdit_1x_ampl_lower->setEnabled(false);
|
ui->lineEdit_1x_ampl_lower->setEnabled(false);
|
||||||
|
@ -145,23 +145,6 @@ void SingleRelay::OnButtonGroup(QAbstractButton *slot_btn) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SingleRelay::on_pushButton_enter_clicked()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void SingleRelay::on_pushButton_clr_clicked()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void SingleRelay::on_pushButton_backspace_clicked()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
void SingleRelay::keyPressEvent(QKeyEvent *event) {
|
void SingleRelay::keyPressEvent(QKeyEvent *event) {
|
||||||
// if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) {
|
// if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) {
|
||||||
// removeLastElement();
|
// removeLastElement();
|
||||||
|
@ -28,12 +28,6 @@ class SingleRelay : public QDialog {
|
|||||||
void on_pushButton_cancel_clicked();
|
void on_pushButton_cancel_clicked();
|
||||||
void OnButtonGroup(QAbstractButton *);
|
void OnButtonGroup(QAbstractButton *);
|
||||||
|
|
||||||
void on_pushButton_enter_clicked();
|
|
||||||
|
|
||||||
void on_pushButton_backspace_clicked();
|
|
||||||
|
|
||||||
void on_pushButton_clr_clicked();
|
|
||||||
|
|
||||||
void on_pushButton_confirm_clicked();
|
void on_pushButton_confirm_clicked();
|
||||||
|
|
||||||
void onComboBoxIndexChanged(int index);
|
void onComboBoxIndexChanged(int index);
|
||||||
|
@ -11,13 +11,13 @@
|
|||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>继电器组态</string>
|
<string>单一继电器组态</string>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QLabel" name="label_4">
|
<widget class="QLabel" name="label_4">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>240</x>
|
<x>620</x>
|
||||||
<y>360</y>
|
<y>20</y>
|
||||||
<width>91</width>
|
<width>91</width>
|
||||||
<height>16</height>
|
<height>16</height>
|
||||||
</rect>
|
</rect>
|
||||||
@ -55,8 +55,8 @@
|
|||||||
<widget class="QLabel" name="label_3">
|
<widget class="QLabel" name="label_3">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>620</x>
|
<x>230</x>
|
||||||
<y>10</y>
|
<y>350</y>
|
||||||
<width>111</width>
|
<width>111</width>
|
||||||
<height>16</height>
|
<height>16</height>
|
||||||
</rect>
|
</rect>
|
||||||
@ -223,19 +223,6 @@
|
|||||||
<string>继电器槽位:</string>
|
<string>继电器槽位:</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QPushButton" name="pushButton_enter">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>630</x>
|
|
||||||
<y>230</y>
|
|
||||||
<width>61</width>
|
|
||||||
<height>71</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Enter</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
<widget class="QPushButton" name="pushButton_help">
|
<widget class="QPushButton" name="pushButton_help">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
@ -252,32 +239,6 @@
|
|||||||
<string>帮 助</string>
|
<string>帮 助</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QPushButton" name="pushButton_clr">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>710</x>
|
|
||||||
<y>270</y>
|
|
||||||
<width>61</width>
|
|
||||||
<height>31</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>CLR</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
<widget class="QPushButton" name="pushButton_backspace">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>710</x>
|
|
||||||
<y>230</y>
|
|
||||||
<width>61</width>
|
|
||||||
<height>31</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string><---</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
<widget class="QPushButton" name="pushButton_cancel">
|
<widget class="QPushButton" name="pushButton_cancel">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
@ -291,19 +252,6 @@
|
|||||||
<string>取 消</string>
|
<string>取 消</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QPushButton" name="pushButton_alert_signal">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>620</x>
|
|
||||||
<y>320</y>
|
|
||||||
<width>91</width>
|
|
||||||
<height>31</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>总告警信号</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
<widget class="QWidget" name="widget" native="true">
|
<widget class="QWidget" name="widget" native="true">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
@ -987,20 +935,20 @@
|
|||||||
<widget class="QWidget" name="widget_relay" native="true">
|
<widget class="QWidget" name="widget_relay" native="true">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>240</x>
|
<x>620</x>
|
||||||
<y>380</y>
|
<y>40</y>
|
||||||
<width>561</width>
|
<width>281</width>
|
||||||
<height>131</height>
|
<height>301</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="widget_available" native="true">
|
<widget class="QWidget" name="widget_available" native="true">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>620</x>
|
<x>230</x>
|
||||||
<y>40</y>
|
<y>380</y>
|
||||||
<width>291</width>
|
<width>371</width>
|
||||||
<height>181</height>
|
<height>131</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
|
@ -636,7 +636,7 @@
|
|||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>480</x>
|
<x>480</x>
|
||||||
<y>10</y>
|
<y>20</y>
|
||||||
<width>191</width>
|
<width>191</width>
|
||||||
<height>91</height>
|
<height>91</height>
|
||||||
</rect>
|
</rect>
|
||||||
@ -1000,7 +1000,7 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>60</x>
|
<x>60</x>
|
||||||
<y>310</y>
|
<y>310</y>
|
||||||
<width>81</width>
|
<width>71</width>
|
||||||
<height>22</height>
|
<height>22</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
@ -2821,7 +2821,7 @@
|
|||||||
<connections/>
|
<connections/>
|
||||||
<buttongroups>
|
<buttongroups>
|
||||||
<buttongroup name="buttonGroup_3"/>
|
<buttongroup name="buttonGroup_3"/>
|
||||||
<buttongroup name="buttonGroup"/>
|
|
||||||
<buttongroup name="buttonGroup_2"/>
|
<buttongroup name="buttonGroup_2"/>
|
||||||
|
<buttongroup name="buttonGroup"/>
|
||||||
</buttongroups>
|
</buttongroups>
|
||||||
</ui>
|
</ui>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user