#ifndef CAMERA_H #define CAMERA_H #include #include #include #include #include #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) 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(); auto file = std::make_shared("logs/dvr.log", 1048576 * 5, 14); console->set_level(spdlog::level::debug); file->set_level(spdlog::level::info); std::vector sinks {console, file}; std::string label = "dvr"; if (auto that = spdlog::get(label)) { Camera::log = that; return; } auto log = std::make_shared(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 presets(); bool addPreset(QJsonObject packet); /** * 获取对应可见光 */ QString getViCameraIP(); CaptureData capture(bool append = true); private slots: void onTemperatureDataReady(int presetNo, QVector items); private: static QMutex mutex; static QHash 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 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