Files
dvr/camera.h
2026-02-08 08:58:29 +08:00

181 lines
4.6 KiB
C++

#ifndef CAMERA_H
#define CAMERA_H
#include <QDebug>
#include <QMutex>
#include <QtConcurrent/QtConcurrent>
#include <QJsonDocument>
#include <QJsonObject>
#include "spdlog/spdlog.h"
#include "spdlog/sinks/stdout_color_sinks.h"
#include "spdlog/sinks/rotating_file_sink.h"
#include "hk-net-sdk.h"
#include "hk-net-sdk-inside.h"
#include "mongoose.h"
#include "camera_info.h"
Q_DECLARE_METATYPE(QVector<STRU_NDSWN_TEMPERATURE_UPLOAD>)
struct CaptureData {
bool ok;
QByteArray image;
};
enum InfraredType {
HEIKA,
STATE_GRID,
NEW_STATE_GRID,
UNKNOWN
};
class Camera : public QObject
{
Q_OBJECT
public:
// 创建仪器日志
static void createLogger() {
auto console = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
auto file = std::make_shared<spdlog::sinks::rotating_file_sink_mt>("logs/dvr.log", 1048576 * 5, 14);
console->set_level(spdlog::level::debug);
file->set_level(spdlog::level::info);
std::vector<spdlog::sink_ptr> sinks {console, file};
std::string label = "dvr";
if (auto that = spdlog::get(label)) {
Camera::log = that;
return;
}
auto log = std::make_shared<spdlog::logger>(label, sinks.begin(), sinks.end());
log->set_level(spdlog::level::debug);
log->set_pattern("%Y-%m-%d %H:%M:%S [%l] - %v");
spdlog::register_logger(log);
Camera::log = log;
}
// 回调保活
static void keepalive() {
QTimer* timer = new QTimer();
timer->setInterval(10000);
timer->start();
connect(timer, &QTimer::timeout, []() {
for (Camera* camera : instances) {
if (camera && camera->realtiming && QDateTime::currentMSecsSinceEpoch() - camera->heartbeat >= 30000) {
log->info("{} |> 重新开启回调", camera->toString());
camera->startRealtimeTemperatureCallback();
}
}
});
}
static Camera* of(CameraType cameraType, QString ip, unsigned int port, QString username, QString password);
static Camera* of(CameraInfo cameraInfo);
CameraType getCameraType() const { return cameraType; }
QString getIP() const { return ip; }
unsigned int getPort() const { return port; }
std::string toString() const {
return QString("Camera[%1:%2]").arg(ip).arg(port).toStdString();
}
/**
* 登录
*/
bool login();
/**
* 登出
*/
void logout();
/**
* 开启实时温度回调
*/
void startRealtimeTemperatureCallback();
/**
* 停止实时温度回调
*/
void stopRealtimeTemperatureCallback();
/**
* 套接字加入
*/
void attach(struct mg_connection *conn);
/**
* 套接字离开
*/
void unattach();
/**
* 已设置和特殊预置位
*/
std::vector<STRU_PRESET_CONFIG> presets();
bool addPreset(QJsonObject packet);
/**
* 获取对应可见光
*/
QString getViCameraIP();
CaptureData capture(bool append = true);
private slots:
void onTemperatureDataReady(int presetNo, QVector<STRU_NDSWN_TEMPERATURE_UPLOAD> items);
private:
static QMutex mutex;
static QHash<QString, Camera*> instances;
static bool temperatureCallback(int ch, int presetNo, STRU_NDSWN_TEMPERATURE_UPLOAD* data, unsigned int len, void* user);
static QString cameraKey(CameraType type, QString ip);
static inline const QByteArray PING = QJsonDocument(QJsonObject{{"event", "ping"}}).toJson(QJsonDocument::Compact);
static inline const QByteArray PRESET_NO_ZERO = QJsonDocument(QJsonObject{{"event", "temperature"},{"payload", QJsonObject{{"presetNo", 0}, {"shapes", QJsonArray()}}}}).toJson(QJsonDocument::Compact);
static std::shared_ptr<spdlog::logger> log;
Camera(CameraType cameraType, QString ip, unsigned int port, QString username, QString password);
Camera(const Camera&) = delete;
Camera& operator=(const Camera&) = delete;
void broadcast(QByteArray buffer);
// 红外图片格式
InfraredType getInfraredType(QByteArray buffer);
CameraType cameraType;
QString ip;
unsigned int port;
QString username;
QString password;
bool connected = false;
HKHANDLE ptr = nullptr; // 句柄
struct mg_connection* conn;
// 业务控制
qint64 lastTickAt = QDateTime::currentMSecsSinceEpoch();
bool realtiming = false;
qint64 heartbeat = QDateTime::currentMSecsSinceEpoch();
int stayIn = 0;
qint64 stayInAt = QDateTime::currentMSecsSinceEpoch();
};
#endif // CAMERA_H