/*! \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 { PIIODEVICE(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)(property("playMode").toInt());} //! Current directory where billogs wiil be saved PIString logDir() const {return property("logDir").toString();} //! Returns current file prefix PIString filePrefix() const {return property("filePrefix").toString();} //! Current LogDir, returns directory where billogs wiil be saved int defaultID() const {return property("defaultID").toInt();} //! Returns current play speed float playSpeed() const {return property("playSpeed").toFloat();} //! Returns if rapid start enabled bool rapidStart() const {return property("rapidStart").toBool();} //! Set \a PlayMode void setPlayMode(PlayMode mode) {setProperty("playMode", (int)mode);} //! Set path to directory where binlogs will be saved void setLogDir(const PIString & path) {setProperty("logDir", path);} //! Set file prefix, used to void setFilePrefix(const PIString & prefix) {setProperty("filePrefix", prefix);} //! Set defaultID, used in \a write function void setDefaultID(int id) {setProperty("defaultID", id);} //! If enabled BinLog \a ThreadedRead starts without delay for first record, e.g. first record will be readed immediately void setRapidStart(bool enabled) {setProperty("rapidStart", enabled);} // /** \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 if \a playMode = \a PlayVariableSpeed, default value 1.0 void setPlaySpeed(float speed) {setProperty("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(defaultID(), data, size);} //! Array of ID, that BinLog can read from binlog file, when use \a read function, or in \a ThreadedRead PIVector filterID; //! Go to begin of BinLog file void restart(); PIString constructFullPath() const; //! \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: PIString fullPathPrefix() const {return "binlog";} void configureFromFullPath(const PIString & full_path); 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; BinLogRecord lastrecord; PISystemTime startlogtime; //BinLogRecord nextrecord; double play_time; //milliseconds //int real_speedX; // in X bool is_started, is_thread_ok; uchar binlog_sig[PIBINARYLOG_SIGNATURE_SIZE]; }; #endif // PIBINARYLOG_H