Initial commit based on common repo commit ffeb9c9b
This commit is contained in:
420
libs/gempa/caps/packet.h
Normal file
420
libs/gempa/caps/packet.h
Normal file
@@ -0,0 +1,420 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2009 by gempa GmbH *
|
||||
* *
|
||||
* All Rights Reserved. *
|
||||
* *
|
||||
* NOTICE: All information contained herein is, and remains *
|
||||
* the property of gempa GmbH and its suppliers, if any. The intellectual *
|
||||
* and technical concepts contained herein are proprietary to gempa GmbH *
|
||||
* and its suppliers. *
|
||||
* Dissemination of this information or reproduction of this material *
|
||||
* is strictly forbidden unless prior written permission is obtained *
|
||||
* from gempa GmbH. *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef GEMPA_CAPS_PACKET_H
|
||||
#define GEMPA_CAPS_PACKET_H
|
||||
|
||||
#include <gempa/caps/api.h>
|
||||
|
||||
#include <gempa/caps/endianess.h>
|
||||
#include <gempa/caps/datetime.h>
|
||||
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
|
||||
namespace Gempa {
|
||||
namespace CAPS {
|
||||
|
||||
|
||||
enum PacketType {
|
||||
UnknownPacket = 0,
|
||||
RawDataPacket,
|
||||
MSEEDPacket,
|
||||
ANYPacket,
|
||||
RTCM2Packet,
|
||||
MetaDataPacket,
|
||||
FixedRawDataPacket,
|
||||
PacketTypeCount
|
||||
};
|
||||
|
||||
|
||||
enum DataType {
|
||||
DT_Unknown = 0,
|
||||
DT_DOUBLE = 1,
|
||||
DT_FLOAT = 2,
|
||||
DT_INT64 = 100,
|
||||
DT_INT32 = 101,
|
||||
DT_INT16 = 102,
|
||||
DT_INT8 = 103
|
||||
};
|
||||
|
||||
|
||||
union UOM {
|
||||
char str[4];
|
||||
int32_t ID;
|
||||
};
|
||||
|
||||
|
||||
union Quality {
|
||||
char str[4];
|
||||
int32_t ID;
|
||||
};
|
||||
|
||||
|
||||
struct SC_GEMPA_CAPS_API TimeStamp {
|
||||
int16_t year; /* year, eg. 2003 */
|
||||
uint16_t yday; /* day of year (1-366) */
|
||||
uint8_t hour; /* hour (0-23) */
|
||||
uint8_t minute; /* minute (0-59) */
|
||||
uint8_t second; /* second (0-59), 60 if leap second */
|
||||
uint8_t unused; /* unused byte */
|
||||
int32_t usec; /* microsecond (0-999999) */
|
||||
};
|
||||
|
||||
|
||||
struct SC_GEMPA_CAPS_API PacketDataHeader {
|
||||
PacketDataHeader()
|
||||
: version(1), packetType(UnknownPacket) {
|
||||
unitOfMeasurement.ID = 0;
|
||||
}
|
||||
|
||||
PacketDataHeader(uint16_t version)
|
||||
: version(version)
|
||||
, packetType(UnknownPacket) {
|
||||
unitOfMeasurement.ID = 0;
|
||||
}
|
||||
|
||||
uint16_t version;
|
||||
PacketType packetType;
|
||||
UOM unitOfMeasurement;
|
||||
|
||||
bool setUOM(const char *type);
|
||||
std::string uom(char fill = '\0') const;
|
||||
|
||||
bool operator!=(const PacketDataHeader &other) const;
|
||||
|
||||
int dataSize() const {
|
||||
return sizeof(version) + sizeof((char)packetType) +
|
||||
sizeof(unitOfMeasurement.ID);
|
||||
}
|
||||
|
||||
bool put(std::streambuf &buf) const {
|
||||
Endianess::Writer put(buf);
|
||||
|
||||
char type = char(packetType);
|
||||
|
||||
put(version);
|
||||
put(type);
|
||||
put(unitOfMeasurement.ID);
|
||||
|
||||
return put.good;
|
||||
}
|
||||
|
||||
bool get(std::streambuf &buf) {
|
||||
Endianess::Reader get(buf);
|
||||
|
||||
char type;
|
||||
|
||||
get(version);
|
||||
get(type); packetType = PacketType(type);
|
||||
get(unitOfMeasurement.ID);
|
||||
|
||||
return get.good;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct SC_GEMPA_CAPS_API PacketDataHeaderV2 : PacketDataHeader {
|
||||
PacketDataHeaderV2()
|
||||
: PacketDataHeader(2)
|
||||
, samplingFrequencyNumerator(0)
|
||||
, samplingFrequencyDenominator(0) {}
|
||||
|
||||
uint16_t samplingFrequencyNumerator;
|
||||
uint16_t samplingFrequencyDenominator;
|
||||
Quality quality;
|
||||
|
||||
bool operator!=(const PacketDataHeaderV2 &other) const;
|
||||
|
||||
int dataSize() const {
|
||||
return PacketDataHeader::dataSize() +
|
||||
sizeof(samplingFrequencyNumerator) +
|
||||
sizeof(samplingFrequencyDenominator) +
|
||||
sizeof(quality);
|
||||
}
|
||||
|
||||
bool put(std::streambuf &buf) const {
|
||||
Endianess::Writer put(buf);
|
||||
|
||||
PacketDataHeader::put(buf);
|
||||
|
||||
put(samplingFrequencyNumerator);
|
||||
put(samplingFrequencyDenominator);
|
||||
put(quality);
|
||||
|
||||
return put.good;
|
||||
}
|
||||
|
||||
bool get(std::streambuf &buf) {
|
||||
Endianess::Reader get(buf);
|
||||
|
||||
PacketDataHeader::get(buf);
|
||||
|
||||
get(samplingFrequencyNumerator);
|
||||
get(samplingFrequencyDenominator);
|
||||
get(quality);
|
||||
|
||||
return get.good;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
enum StreamIDComponent {
|
||||
NetworkCode = 0,
|
||||
StationCode = 1,
|
||||
LocationCode = 2,
|
||||
ChannelCode = 3,
|
||||
StreamIDComponentSize
|
||||
};
|
||||
|
||||
|
||||
struct SC_GEMPA_CAPS_API PacketHeaderV1 {
|
||||
uint8_t SIDSize[4]; /* number of bytes of stream ID components */
|
||||
uint16_t size; /* number of data bytes */
|
||||
|
||||
bool put(std::streambuf &buf) {
|
||||
Endianess::Writer put(buf);
|
||||
for ( int i = 0; i < 4; ++i )
|
||||
put(SIDSize[i]);
|
||||
|
||||
put(size);
|
||||
|
||||
return put.good;
|
||||
}
|
||||
|
||||
size_t dataSize() const {
|
||||
return sizeof(uint8_t) * 4 + sizeof(size);
|
||||
}
|
||||
};
|
||||
|
||||
struct SC_GEMPA_CAPS_API PacketHeaderV2 {
|
||||
uint8_t SIDSize[4]; /* number of bytes of stream ID components */
|
||||
uint32_t size; /* number of data bytes */
|
||||
|
||||
bool put(std::streambuf &buf) {
|
||||
Endianess::Writer put(buf);
|
||||
for ( int i = 0; i < 4; ++i )
|
||||
put(SIDSize[i]);
|
||||
|
||||
put(size);
|
||||
|
||||
return put.good;
|
||||
}
|
||||
size_t dataSize() const {
|
||||
return sizeof(uint8_t) * 4 + sizeof(size);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct SC_GEMPA_CAPS_API ResponseHeader {
|
||||
uint16_t id;
|
||||
int32_t size;
|
||||
|
||||
bool get(std::streambuf &buf) {
|
||||
Endianess::Reader get(buf);
|
||||
|
||||
get(id);
|
||||
get(size);
|
||||
|
||||
return get.good;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class SC_GEMPA_CAPS_API DataRecord {
|
||||
public:
|
||||
typedef std::vector<char> Buffer;
|
||||
|
||||
struct Header {
|
||||
DataType dataType{DT_Unknown};
|
||||
TimeStamp samplingTime;
|
||||
uint16_t samplingFrequencyNumerator;
|
||||
uint16_t samplingFrequencyDenominator;
|
||||
Quality quality{};
|
||||
|
||||
Header() = default;
|
||||
|
||||
bool get(std::streambuf &buf) {
|
||||
Endianess::Reader get(buf);
|
||||
char dt;
|
||||
get(dt);
|
||||
dataType = (DataType)dt;
|
||||
quality.ID = 0; // Quality is not yet part of the header stream
|
||||
|
||||
get(samplingTime.year);
|
||||
get(samplingTime.yday);
|
||||
get(samplingTime.hour);
|
||||
get(samplingTime.minute);
|
||||
get(samplingTime.second);
|
||||
get(samplingTime.usec);
|
||||
get(samplingFrequencyNumerator);
|
||||
get(samplingFrequencyDenominator);
|
||||
|
||||
return get.good;
|
||||
}
|
||||
|
||||
bool put(std::streambuf &buf) const;
|
||||
|
||||
int dataSize() const {
|
||||
return sizeof(samplingTime.year) +
|
||||
sizeof(samplingTime.yday) +
|
||||
sizeof(samplingTime.hour) +
|
||||
sizeof(samplingTime.minute) +
|
||||
sizeof(samplingTime.second) +
|
||||
sizeof(samplingTime.usec) +
|
||||
sizeof(samplingFrequencyNumerator) +
|
||||
sizeof(samplingFrequencyDenominator) +
|
||||
sizeof(char);
|
||||
}
|
||||
|
||||
bool compatible(const Header &other) const;
|
||||
bool operator!=(const Header &other) const;
|
||||
|
||||
void setSamplingTime(const Time ×tamp);
|
||||
};
|
||||
|
||||
enum ReadStatusCode {
|
||||
RS_Error = 0,
|
||||
RS_Complete = 1,
|
||||
RS_Partial = 2,
|
||||
RS_BeforeTimeWindow = 3,
|
||||
RS_AfterTimeWindow = 4,
|
||||
RS_Max
|
||||
};
|
||||
|
||||
class ReadStatus {
|
||||
public:
|
||||
ReadStatus() {}
|
||||
ReadStatus(ReadStatusCode code) : _code(code) {}
|
||||
ReadStatus(const ReadStatus &other) : _code(other._code) {}
|
||||
|
||||
public:
|
||||
ReadStatus &operator=(const ReadStatus &other) { _code = other._code; return *this; }
|
||||
operator ReadStatusCode() const { return _code; }
|
||||
|
||||
private:
|
||||
operator bool() { return _code != RS_Error; }
|
||||
|
||||
private:
|
||||
ReadStatusCode _code;
|
||||
};
|
||||
|
||||
public:
|
||||
virtual ~DataRecord();
|
||||
|
||||
virtual const char *formatName() const = 0;
|
||||
|
||||
virtual bool readMetaData(std::streambuf &buf, int size,
|
||||
Header &header,
|
||||
Time &startTime, Time &endTime) = 0;
|
||||
|
||||
//! Returns if data trimming is supported
|
||||
virtual bool canTrim() const = 0;
|
||||
|
||||
//! Returns if data merging is possible without modifying
|
||||
//! preceding data
|
||||
virtual bool canMerge() const = 0;
|
||||
|
||||
//! Trims a record to start and end time. Trimming
|
||||
//! should not modify any data but give access to trimmed
|
||||
//! start and end times and the resulting data size. The trimming
|
||||
//! also influences writing the record to a stream.
|
||||
//! Trimming requires the resulting start time being greater
|
||||
//! or equal than the requested start time.
|
||||
//! (Un)Trimming to the original record is semantically
|
||||
//! equal to passing an invalid start and end time.
|
||||
//! It returns true if trimming has been done or false
|
||||
//! if an error occured or trimming is not supported.
|
||||
virtual bool trim(const Time &start, const Time &end) const = 0;
|
||||
|
||||
//! Returns the data size in bytes if the current state would
|
||||
//! be written to a stream. Trimming has also to be taken into
|
||||
//! account while calculating the size.
|
||||
virtual size_t dataSize(bool withHeader = true) const = 0;
|
||||
|
||||
//! Reads the packet from a streambuf and trims the data
|
||||
//! if possible to start and end. If maxBytes is greater
|
||||
//! than 0 then the record should not use more than this
|
||||
//! size of memory (in bytes). If not the complete record
|
||||
//! has been read, RS_Partial must be returned, RS_Complete
|
||||
//! otherwise.
|
||||
virtual ReadStatus get(std::streambuf &buf, int size,
|
||||
const Time &start = Time(), const Time &end = Time(),
|
||||
int maxBytes = -1) = 0;
|
||||
|
||||
//! writes the packet to a streambuf and trims the data
|
||||
//! if possible to start and end
|
||||
virtual bool put(std::streambuf &buf, bool withHeader = true) const = 0;
|
||||
|
||||
//! Returns the meta information of the data if supported
|
||||
virtual const Header *header() const = 0;
|
||||
|
||||
//! Returns the start time of the record
|
||||
virtual Time startTime() const = 0;
|
||||
|
||||
//! Returns the end time of the record
|
||||
virtual Time endTime() const = 0;
|
||||
|
||||
//! Returns the packet type of the record
|
||||
virtual PacketType packetType() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Returns the data vector to be filled by the caller
|
||||
* @return The pointer to the internal buffer
|
||||
*/
|
||||
virtual Buffer *buffer() { return &_data; }
|
||||
|
||||
/**
|
||||
* @brief Returns pointer to raw data. If the record
|
||||
* is compressed it will be uncompressed
|
||||
* @return The pointer to the raw data
|
||||
*/
|
||||
virtual Buffer *data() { return &_data; }
|
||||
|
||||
protected:
|
||||
Buffer _data;
|
||||
};
|
||||
|
||||
typedef boost::shared_ptr<DataRecord> DataRecordPtr;
|
||||
|
||||
|
||||
struct RawPacket {
|
||||
PacketDataHeader header;
|
||||
std::string SID[4];
|
||||
std::vector<char> data;
|
||||
DataRecord *record;
|
||||
};
|
||||
|
||||
struct MetaPacket {
|
||||
std::string SID[4];
|
||||
PacketDataHeader packetDataHeader;
|
||||
DataRecord *record;
|
||||
DataRecord::Header recordHeader;
|
||||
Time startTime;
|
||||
Time endTime;
|
||||
Time timestamp;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user