GrabBag/App/BeltTearing/BeltTearingServer/TearingTcpProtocol.h

209 lines
5.8 KiB
C
Raw Normal View History

#ifndef TEARINGTCPPROTOCOL_H
#define TEARINGTCPPROTOCOL_H
#include <QObject>
#include <QJsonObject>
#include <QJsonDocument>
#include <QByteArray>
#include <QBuffer>
#include <QImage>
#include <QDateTime>
#include <QTimer>
#include <QMap>
#include <functional>
#include "IYTCPServer.h"
#include "beltTearingDetection_Export.h"
// 帧格式定义
#define FRAME_HEADER "##START#" // 8字节帧头
#define FRAME_TAIL "#END" // 4字节帧尾
#define FRAME_HEADER_SIZE 8
#define FRAME_TAIL_SIZE 4
#define FRAME_LENGTH_SIZE 8
/**
* @brief
*/
enum class TcpMessageType
{
DETECT_RESULT, // 撕裂检测结果上报
SET_SPEED, // 设置速度命令
SET_CONTROL, // 启停控制命令
CMD_RESPONSE, // 命令应答
HEARTBEAT, // 心跳消息
HEARTBEAT_ACK, // 心跳应答
UNKNOWN // 未知消息类型
};
/**
* @brief
* @param speed mm/s
*/
using SpeedCallback = std::function<void(int speed)>;
/**
* @brief
* @param control true-false-
*/
using ControlCallback = std::function<void(bool control)>;
/**
* @brief TCP通信协议类
* TCP通信协议
* TCP通信协议.md
*/
class TearingTcpProtocol : public QObject
{
Q_OBJECT
public:
explicit TearingTcpProtocol(IYTCPServer* tcpServer, QObject *parent = nullptr);
~TearingTcpProtocol();
/**
* @brief
* @param heartbeatInterval 30
*/
void start(int heartbeatInterval = 30);
/**
* @brief
*/
void stop();
/**
* @brief
* @param results
* @param visImage
*/
void sendDetectResult(const std::vector<SSG_beltTearingInfo>& results, const QImage& visImage);
/**
* @brief
* @param pClient
* @param pData
* @param nLen
*/
void handleReceivedData(const TCPClient* pClient, const char* pData, unsigned int nLen);
/**
* @brief
*/
void setSpeedCallback(const SpeedCallback& callback);
/**
* @brief
*/
void setControlCallback(const ControlCallback& callback);
private slots:
/**
* @brief
*/
void onHeartbeatTimeout();
/**
* @brief
*/
void onClientTimeoutCheck();
private:
/**
* @brief
* @param jsonData JSON数据
* @return
*/
QByteArray buildFrame(const QByteArray& jsonData);
/**
* @brief
* @param data
* @param outJsonData JSON数据数组
* @return
*/
int parseFrames(const QByteArray& data, QList<QByteArray>& outJsonData);
/**
* @brief
* @param msgTypeStr
* @return
*/
TcpMessageType parseMessageType(const QString& msgTypeStr);
/**
* @brief JSON消息
* @param pClient
* @param jsonData JSON数据
*/
void handleJsonMessage(const TCPClient* pClient, const QByteArray& jsonData);
/**
* @brief
* @param pClient
* @param jsonObj JSON对象
*/
void handleSetSpeed(const TCPClient* pClient, const QJsonObject& jsonObj);
/**
* @brief
* @param pClient
* @param jsonObj JSON对象
*/
void handleSetControl(const TCPClient* pClient, const QJsonObject& jsonObj);
/**
* @brief
* @param pClient
* @param jsonObj JSON对象
*/
void handleHeartbeat(const TCPClient* pClient, const QJsonObject& jsonObj);
/**
* @brief
* @param pClient
* @param cmdType
* @param result
* @param errorCode
* @param errorMsg
*/
void sendCommandResponse(const TCPClient* pClient, const QString& cmdType,
bool result, int errorCode, const QString& errorMsg);
/**
* @brief
* @param pClient
*/
void sendHeartbeatAck(const TCPClient* pClient);
/**
* @brief Base64
* @param image
* @return Base64字符串
*/
QString imageToBase64(const QImage& image);
/**
* @brief ID
* @param pClient
* @return ID
*/
QString generateClientId(const TCPClient* pClient);
private:
IYTCPServer* m_tcpServer; // TCP服务器
QTimer* m_heartbeatTimer; // 心跳定时器
QTimer* m_clientCheckTimer; // 客户端超时检查定时器
int m_heartbeatInterval; // 心跳间隔(秒)
int m_clientTimeout; // 客户端超时时间(秒)
// 客户端数据缓冲区
QMap<QString, QByteArray> m_clientBuffers; // 客户端ID -> 数据缓冲区
QMap<QString, qint64> m_clientLastActive; // 客户端ID -> 最后活跃时间
// 回调函数
SpeedCallback m_speedCallback;
ControlCallback m_controlCallback;
};
#endif // TEARINGTCPPROTOCOL_H