/*! \file pibinarylog.h * \brief Binary log */ /* PIP - Platform Independent Primitives Class for write binary data to logfile, and read or playback this data Copyright (C) 2014 Andrey Bychkov work.a.b@yandex.ru This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef PIBINARYLOG_H #define PIBINARYLOG_H #include "pifile.h" #define PIBINARYLOG_VERSION 0x31 #define PIBINARYLOG_SIGNATURE_SIZE 6 class PIBinaryLog: public PIIODevice { PIOBJECT(PIBinaryLog) public: PIBinaryLog(); ~PIBinaryLog() {closeDevice();} //! \brief Play modes for \a PIBinaryLog enum PlayMode { PlayRealTime /*! Play in system real time */ , PlayVariableSpeed /*! Play in software time with speed, set by \a setSpeed. Set by default */ }; //! Current \a PlayMode PlayMode playMode() const {return playmode;} //! Current directory where billogs wiil be saved const PIString & logDir() const {return logdir;} //! Returns current file prefix const PIString & filePrefix() const {return fileprefix;} //! Current LogDir, returns directory where billogs wiil be saved int dafaultID() const {return default_id;} //! Returns current play speed float speed() const {return playspeed;} //! Set \a PlayMode void setPlayMode(PlayMode mode) {playmode = mode;} //! Set path to directory where binlogs will be saved void setLogDir(const PIString & path) {logdir = path;} //! Set file prefix, used to void setFilePrefix(const PIString & prefix) {fileprefix = prefix;} //! Set defaultID, used in \a write function void setDefaultID(int id) {default_id = id;} // /** \brief Set play speed multiplyer, used only in \a PlayMode = \a PlayRealTime default value 1x. // * If "speedX" > 0 than it use as speed increase by X times, else as speed decrease by X times. // * While is running this function does nothing and returns false. If "speedX" is set, returns true.*/ // bool setRealSpeedX(int speedX) {if (speedX == 0 || isRunning()) return false; real_speedX = speedX; return true;} // //! Returns current play speed multiplyer // float realSpeedX() const {return real_speedX;} //! Set play speed, used only in \a PlayMode = \a PlayVariableSpeed, default value 1.0 void setSpeed(float speed) {playspeed = speed;} //! Write one record to BinLog file, with ID = id, id must be greather than 0 int writeBinLog(int id, PIByteArray data) {return writeBinLog(id, data.data(), data.size_s());} int writeBinLog(int id, const void * data, int size); //! Read one record from BinLog file, with ID = id, if id = 0 than any id will be readed PIByteArray readBinLog(int id = 0); int readBinLog(int id, void *read_to, int max_size); //! Return true, if position at the end of BinLog file bool isEnd() {if (!opened_) return true; return file.isEnd();} //! Returns if BinLog file is empty bool isEmpty() {return (file.size() <= PIBINARYLOG_SIGNATURE_SIZE + 1);} int lastReadedID() const {return lastrecord.id;} //! Read one message from binlog file, with ID contains in "filterID" or any ID, if "filterID" is empty int read(void *read_to, int max_size); //! Write one record to BinLog file, with ID = "defaultID" int write(const void * data, int size) {return writeBinLog(default_id, data, size);} //! Array of ID, that BinLog can read from binlog file, when use \a read function, or in \a ThreadedRead PIVector filterID; //! If "RapidStart" enabled, than BinLog \a ThreadedRead starts without delay for first record, e.g. first record will be readed immediately void setRapidStart(bool enabled = false) {rapid_start = enabled;} //! Go to begin of BinLog file void restart(); //! \handlers //! \{ //! \fn PIString createNewFile() //! \brief Open device //! \} //! \events //! \{ //! \fn void fileEnd() //! \brief Create new binlog file in \a logDir, if successful returns filename, else returns empty string. //! Filename is like \a filePrefix + "yyyy_MM_dd__hh_mm_ss.binlog" //! \fn void fileError() //! \brief Raise on file creation error //! \} EVENT_HANDLER(PIString, createNewFile); EVENT(fileEnd) EVENT(fileError) protected: bool openDevice(); bool closeDevice(); bool threadedRead(uchar *readed, int size); private: struct BinLogRecord { int id; int size; PISystemTime timestamp; PIByteArray data; }; bool writeFileHeader(); bool checkFileHeader(); BinLogRecord readRecord(); PIFile file; PIString logdir, fileprefix; BinLogRecord lastrecord; PISystemTime startlogtime; //BinLogRecord nextrecord; PlayMode playmode; double play_time; //milliseconds float playspeed; int default_id; //int real_speedX; // in X bool is_started, rapid_start, is_thread_ok; uchar binlog_sig[PIBINARYLOG_SIGNATURE_SIZE]; }; #endif // PIBINARYLOG_H