CCSDSPack
C++ Library for CCSDS Space Packet manipulation. i.e. generation, extraction, analisys and more
Loading...
Searching...
No Matches
CCSDSPacket.cpp
Go to the documentation of this file.
1#include "CCSDSPacket.h"
2#include "CCSDSDataField.h"
3#include "CCSDSUtils.h"
4#include <algorithm>
5
6//exclude includes when building for MCU
7#ifndef CCSDS_MCU
8 #include "CCSDSConfig.h"
9#endif //CCSDS_MCU
10
13 const auto dataField = m_dataField.serialize();
14 const auto dataFiledSize = static_cast<std::uint16_t>(dataField.size());
15 const auto dataFieldHeaderFlag(m_dataField.getDataFieldHeaderFlag());
16 m_primaryHeader.setDataLength(dataFiledSize);
17 m_primaryHeader.setDataFieldHeaderFlag(dataFieldHeaderFlag);
18 // todo this part needs to be moved out of conditional updating
21 } else {
23 }
25 m_updateStatus = true;
26 }
27}
28
29#ifndef CCSDS_MCU
31 Config cfg;
32 cfg.load(configPath);
33 FORWARD_RESULT(loadFromConfig(cfg));
34 return true;
35}
36
38 std::uint8_t versionNumber;
39 std::uint8_t type;
40 std::uint8_t APID{0};
41 std::uint8_t dataFieldHeaderFlag;
42 std::uint16_t sequenceCount;
43 ESequenceFlag sequenceFlag{};
44 bool segmented{false};
45
46 RET_IF_ERR_MSG(!cfg.isKey( "ccsds_version_number"), ErrorCode::CONFIG_FILE_ERROR,
47 "Config: Missing int field: ccsds_version_number");
49 "Config: Missing bool field: ccsds_type");
50 RET_IF_ERR_MSG(!cfg.isKey("ccsds_data_field_header_flag"), ErrorCode::CONFIG_FILE_ERROR,
51 "Config: Missing bool field: ccsds_data_field_header_flag");
53 "Config: Missing int field: ccsds_APID");
54 RET_IF_ERR_MSG(!cfg.isKey( "ccsds_segmented"), ErrorCode::CONFIG_FILE_ERROR,
55 "Config: Missing bool field: ccsds_segmented");
56
57 ASSIGN_OR_PRINT(versionNumber, cfg.get< int>( "ccsds_version_number"));
58 ASSIGN_OR_PRINT(type, cfg.get<bool>( "ccsds_type"));
59 ASSIGN_OR_PRINT(dataFieldHeaderFlag, cfg.get<bool>("ccsds_data_field_header_flag"));
60 ASSIGN_OR_PRINT(APID, cfg.get< int>( "ccsds_APID"));
61 ASSIGN_OR_PRINT(segmented, cfg.get<bool>( "ccsds_segmented"));
62
63 m_primaryHeader.setVersionNumber(versionNumber);
64 m_primaryHeader.setType(type);
65 m_primaryHeader.setDataFieldHeaderFlag(dataFieldHeaderFlag);
66 m_primaryHeader.setAPID(APID);
67 if (segmented) {
68 sequenceCount = 1;
69 sequenceFlag = FIRST_SEGMENT;
70 }else {
71 sequenceCount = 0;
72 sequenceFlag = UNSEGMENTED;
73 }
74 m_primaryHeader.setSequenceFlags(sequenceFlag);
75 m_primaryHeader.setSequenceCount(sequenceCount);
76
77 if (cfg.isKey( "data_field_size")) { // optional field
78 std::uint16_t dataFieldSize;
79 ASSIGN_OR_PRINT(dataFieldSize, cfg.get< int>( "data_field_size"));
80 m_dataField.setDataPacketSize(dataFieldSize);
81 }
82
83 if (cfg.isKey("define_secondary_header")) { // optional field
84 bool secondaryHeaderFlag{false};
85 ASSIGN_OR_PRINT(secondaryHeaderFlag, cfg.get<bool>("define_secondary_header"));
86 if (secondaryHeaderFlag) {
87 FORWARD_RESULT( m_dataField.setDataFieldHeader(cfg));
88 }
89 }
90
91 if (cfg.isKey("application_data")) { // optional field
92 std::vector<std::uint8_t> applicationData{};
93 ASSIGN_OR_PRINT(applicationData, cfg.get<std::vector<std::uint8_t>>("application_data"));
94 FORWARD_RESULT( m_dataField.setApplicationData(applicationData));
95 }
96
97 return true;
98}
99#endif
100
102 update();
103 return m_CRC16;
104}
105
107 return m_dataField.getDataFieldAvailableBytesSize();
108}
109
111 update();
112 return m_primaryHeader.getDataFieldHeaderFlag();
113}
114
115std::vector<std::uint8_t> CCSDS::Packet::getCRCVectorBytes() {
116 std::vector<std::uint8_t> crc(2);
117 const auto crcVar = getCRC();
118 crc[0] = (crcVar >> 8) & 0xFF; // MSB (Most Significant Byte)
119 crc[1] = crcVar & 0xFF; // LSB (Least Significant Byte)
120 return crc;
121}
122
124 update();
125 return m_dataField;
126}
127
129 update();
130 return m_primaryHeader;
131}
132
134 update();
135 return m_primaryHeader.getFullHeader();
136};
137
138std::vector<std::uint8_t> CCSDS::Packet::getPrimaryHeaderBytes() {
139 update();
140 return m_primaryHeader.serialize();
141}
142
143std::vector<std::uint8_t> CCSDS::Packet::getDataFieldHeaderBytes() {
144 update();
145 return m_dataField.getDataFieldHeaderBytes();
146}
147
148std::vector<std::uint8_t> CCSDS::Packet::getApplicationDataBytes() {
149 update();
150 return m_dataField.getApplicationData();
151}
152
153std::vector<std::uint8_t> CCSDS::Packet::getFullDataFieldBytes() {
154 return m_dataField.serialize();
155}
156
157std::vector<std::uint8_t> CCSDS::Packet::serialize() {
158 auto header = getPrimaryHeaderBytes();
159 auto dataField = m_dataField.serialize();
160 const auto crc = getCRCVectorBytes();
161
162 std::vector<std::uint8_t> packet;
163 packet.reserve(header.size() + dataField.size() + crc.size());
164 packet.insert(packet.end(), header.begin(), header.end());
165 if (!getFullDataFieldBytes().empty()) {
166 packet.insert(packet.end(), dataField.begin(), dataField.end());
167 }
168 packet.insert(packet.end(), crc.begin(), crc.end());
169
170 return packet;
171}
172
173CCSDS::ResultBool CCSDS::Packet::deserialize(const std::vector<std::uint8_t> &data) {
175 "Cannot Deserialize Packet, Invalid Data provided data size must be at least 8 bytes");
176
177 std::vector<std::uint8_t> dataFieldVector;
178 std::copy(data.begin() + 6, data.end(), std::back_inserter(dataFieldVector));
179
180 FORWARD_RESULT(deserialize({data[0], data[1], data[2], data[3], data[4], data[5]}, dataFieldVector));
181
182 return true;
183}
184
185CCSDS::ResultBool CCSDS::Packet::deserialize(const std::vector<std::uint8_t> &data, const std::string &headerType, const std::int32_t headerSize) {
186 RET_IF_ERR_MSG(data.size() <= 8, ErrorCode::INVALID_DATA,
187 "Cannot Deserialize Packet, Invalid Data provided data size must be at least 8 bytes");
188 RET_IF_ERR_MSG(headerType == "BufferHeader", ErrorCode::INVALID_SECONDARY_HEADER_DATA,
189 "Cannot Deserialize Packet, BufferHeader is not of defined size");
190 RET_IF_ERR_MSG(!m_dataField.getDataFieldHeaderFactory().typeIsRegistered(headerType),
192 "Cannot Deserialize Packet, Unregistered Secondary header: " + headerType);
193 std::uint16_t headerDataSizeBytes{0};
194 const auto secondaryHeader = m_dataField.getDataFieldHeaderFactory().create(headerType);
195 if (headerType == "PusC" && headerSize > 0) {
196 headerDataSizeBytes = headerSize;
197 }else {
198 headerDataSizeBytes = secondaryHeader->getSize();
199 }
200
201 std::vector<std::uint8_t> dataFieldHeaderVector;
202 std::copy_n(data.begin() + 6, headerDataSizeBytes, std::back_inserter(dataFieldHeaderVector));
203 FORWARD_RESULT(secondaryHeader->deserialize(dataFieldHeaderVector ));
204 setDataFieldHeader(secondaryHeader);
205
206 if (data.size() > (8 + headerDataSizeBytes)) {
207 std::vector<std::uint8_t> dataFieldVector;
208
209 if (data.size() > (9 + headerDataSizeBytes)) {
210 std::copy(data.begin() + 6 + headerDataSizeBytes, data.end(), std::back_inserter(dataFieldVector));
211 }
212 FORWARD_RESULT(deserialize({data[0], data[1], data[2], data[3], data[4], data[5]}, dataFieldVector));
213 }
214
215 return true;
216}
217
218CCSDS::ResultBool CCSDS::Packet::deserialize(const std::vector<std::uint8_t> &data, const std::uint16_t headerDataSizeBytes) {
219 RET_IF_ERR_MSG(data.size() <= (8 + headerDataSizeBytes), ErrorCode::INVALID_DATA,
220 "Cannot Serialize Packet, Invalid Data provided");
221
222 std::vector<std::uint8_t> secondaryHeader;
223 std::vector<std::uint8_t> dataFieldVector;
224 std::copy(data.begin() + 6, data.begin() + 6 + headerDataSizeBytes, std::back_inserter(secondaryHeader));
225 FORWARD_RESULT(m_dataField.setDataFieldHeader(secondaryHeader));
226 if (data.size() > (7 + headerDataSizeBytes)) {
227 std::copy(data.begin() + 6 + headerDataSizeBytes, data.end(), std::back_inserter(dataFieldVector));
228 }
229 FORWARD_RESULT(deserialize({data[0], data[1], data[2], data[3], data[4], data[5]}, dataFieldVector));
230 return true;
231}
232
233CCSDS::ResultBool CCSDS::Packet::deserialize(const std::vector<std::uint8_t> &headerData, const std::vector<std::uint8_t> &data) {
234 RET_IF_ERR_MSG(headerData.size() != 6, ErrorCode::INVALID_HEADER_DATA,
235 "Cannot Deserialize Packet, Invalid Header Data provided.");
236 FORWARD_RESULT(m_primaryHeader.deserialize( headerData ));
237 m_sequenceCounter = m_primaryHeader.getSequenceCount();
238
240 "Cannot Deserialize Packet, Invalid Data provided, at least CRC is required.");
241
242 std::vector<uint8_t> dataCopy;
243 m_CRC16 = (data[data.size() - 2] << 8) + data.back();
244
245 if (data.size() == 2) return true; // returns since no application data is to be written.
246
247 std::copy(data.begin(), data.end() - 2, std::back_inserter(dataCopy));
248 FORWARD_RESULT(m_dataField.setApplicationData(dataCopy));
249
250 return true;;
251}
252
254 // where 8 is derived from 6 bytes for Primary header and 2 bytes for CRC16.
255 return 8 + m_dataField.getDataFieldUsedBytesSize();
256}
257
259 FORWARD_RESULT(m_primaryHeader.setData( data ));
260 m_sequenceCounter = m_primaryHeader.getSequenceCount();
261 m_updateStatus = false;
262 return true;
263}
264
265CCSDS::ResultBool CCSDS::Packet::setPrimaryHeader(const std::vector<uint8_t> &data) {
266 FORWARD_RESULT(m_primaryHeader.deserialize( data ));
267 m_sequenceCounter = m_primaryHeader.getSequenceCount();
268 m_updateStatus = false;
269 return true;
270}
271
273 m_primaryHeader = header;
274}
275
277 m_primaryHeader.setData(data);
278 m_sequenceCounter = m_primaryHeader.getSequenceCount();
279 m_updateStatus = false;
280}
281
282void CCSDS::Packet::setDataFieldHeader(const std::shared_ptr<SecondaryHeaderAbstract> &header) {
283 m_dataField.setDataFieldHeader(header);
284 m_updateStatus = false;
285}
286
287CCSDS::ResultBool CCSDS::Packet::setDataFieldHeader(const std::vector<uint8_t> &data, const std::string &headerType) {
288 FORWARD_RESULT(m_dataField.setDataFieldHeader( data, headerType ));
289 m_updateStatus = false;
290 return true;
291}
292
293CCSDS::ResultBool CCSDS::Packet::setDataFieldHeader(const std::uint8_t *pData, const size_t sizeData,
294 const std::string &headerType) {
295 FORWARD_RESULT(m_dataField.setDataFieldHeader( pData, sizeData, headerType ));
296 m_updateStatus = false;
297 return true;
298}
299
300CCSDS::ResultBool CCSDS::Packet::setDataFieldHeader(const std::vector<uint8_t> &data) {
301 FORWARD_RESULT(m_dataField.setDataFieldHeader( data ));
302 m_updateStatus = false;
303 return true;
304}
305
306CCSDS::ResultBool CCSDS::Packet::setDataFieldHeader(const std::uint8_t *pData, const size_t sizeData) {
307 FORWARD_RESULT(m_dataField.setDataFieldHeader( pData,sizeData ));
308 m_updateStatus = false;
309 return true;;
310}
311
312CCSDS::ResultBool CCSDS::Packet::setApplicationData(const std::vector<std::uint8_t> &data) {
313 FORWARD_RESULT(m_dataField.setApplicationData( data ));
314 m_updateStatus = false;
315 return true;
316}
317
318CCSDS::ResultBool CCSDS::Packet::setApplicationData(const std::uint8_t *pData, const size_t sizeData) {
319 FORWARD_RESULT(m_dataField.setApplicationData( pData,sizeData ));
320 m_updateStatus = false;
321 return true;
322}
323
325 m_primaryHeader.setSequenceFlags(flags);
326 m_updateStatus = false;
327}
328
330 RET_IF_ERR_MSG(m_primaryHeader.getSequenceFlags() == UNSEGMENTED && count != 0, ErrorCode::INVALID_DATA,
331 "Unable to set non 0 value for UNSEGMENTED packet");
332 m_sequenceCounter = count;
333 m_updateStatus = false;
334 return true;
335}
336
337void CCSDS::Packet::setDataFieldSize(const std::uint16_t size) {
338 m_dataField.setDataPacketSize(size);
339}
340
342 m_enableUpdatePacket = enable;
343 m_dataField.setDataFieldHeaderAutoUpdateStatus(enable);
344}
#define RET_IF_ERR_MSG(condition, errorCode, message)
Macro to return an error with an error message if a condition is met.
#define ASSIGN_OR_PRINT(var, result)
Macro to assign a result value or print an error message.
#define FORWARD_RESULT(result)
Macro to return a result as-is (for functions returning Result<T>).
uint16_t crc16(const std::vector< std::uint8_t > &data, std::uint16_t polynomial=0x1021, std::uint16_t initialValue=0xFFFF, std::uint16_t finalXorValue=0x0000)
Computes the CRC-16 checksum for a given data vector with configurable parameters.
Represents the data field of a CCSDS packet.
std::vector< std::uint8_t > serialize()
Retrieves the full data field by combining the data field header and application data.
bool getDataFieldHeaderFlag() const
retrieves true if a known secondary header has been set
Manages the decomposition and manipulation of CCSDS primary headers.
Definition CCSDSHeader.h:80
void setDataLength(const std::uint16_t &value)
16 bits
void setSequenceCount(const std::uint16_t &value)
14 bits
void setDataFieldHeaderFlag(const std::uint8_t &value)
1 bits
std::uint8_t getSequenceFlags() const
2 bits
Definition CCSDSHeader.h:88
ResultBool setData(const std::uint64_t &data)
Sets the header data from a 64-bit integer representation.
bool m_updateStatus
When setting data thus value should be set to false.
std::vector< uint8_t > getPrimaryHeaderBytes()
Retrieves the primary header of the packet as a vector of bytes.
void update()
Updates Primary headers data field size.
std::vector< uint8_t > getCRCVectorBytes()
Retrieves the CRC-16 checksum as a vector of bytes.
void setUpdatePacketEnable(bool enable)
needs to be called as soon as possible, probably also from constructor.
ResultBool setSequenceCount(std::uint16_t count)
Sets the sequence count for the packet.
bool getDataFieldHeaderFlag()
@ returns the data field header flag
void setDataFieldHeader(const std::shared_ptr< SecondaryHeaderAbstract > &header)
Sets the data field header using the provided SecondaryHeaderAbstract derived header.
std::uint16_t m_sequenceCounter
Header m_primaryHeader
6 bytes / 48 bits / 12 hex
std::uint64_t getPrimaryHeader64bit()
Retrieves the primary header of the packet.
DataField m_dataField
variable
ResultBool loadFromConfig(const Config &cfg)
Loads a packet from a configuration object, including secondary header if present.
std::uint16_t getCRC()
Computes and retrieves the CRC-16 checksum of the packet.
std::uint16_t getDataFieldMaximumSize() const
returns the maximum data field size
void setSequenceFlags(ESequenceFlag flags)
Sets the sequence flags for the packet's primary header.
std::vector< uint8_t > getFullDataFieldBytes()
Retrieves the full data field data.
std::vector< uint8_t > serialize()
Retrieves the full packet as a vector of bytes.
ResultBool loadFromConfigFile(const std::string &configPath)
Loads a packet from a configuration file, including secondary header if present.
ResultBool setApplicationData(const std::vector< std::uint8_t > &data)
Sets the application data for the packet.
std::uint16_t m_CRC16
Cyclic Redundancy check 16 bits.
std::vector< uint8_t > getDataFieldHeaderBytes()
Retrieves the secondary header data from the data field.
void setPrimaryHeader(PrimaryHeader data)
Sets the primary header using the provided PrimaryHeader object.
ResultBool deserialize(const std::vector< std::uint8_t > &data)
Deserializes a vector of bytes into a CCSDS packet.
std::uint16_t getFullPacketLength()
Retrieves the current size of the CCSDS Packet.
Header & getPrimaryHeader()
returns the CCSDS packet's Primary Header.
std::vector< uint8_t > getApplicationDataBytes()
Retrieves the application data from the data field.
DataField & getDataField()
returns the CCSDS packet's DataField.
bool m_enableUpdatePacket
Enables primary header and secondary header update.
void setDataFieldSize(std::uint16_t size)
Sets the maximum data packet size for the CCSDS DataField.
CRC16Config m_CRC16Config
structure holding configuration of crc calculation.
Encapsulates a result that can hold either a value or an Error.
Definition CCSDSResult.h:82
Parses and stores config values from custom file format.
Definition CCSDSConfig.h:11
bool isKey(const std::string &key) const
CCSDS::ResultBool load(const std::string &filename)
Load config file.
CCSDS::Result< T > get(const std::string &key) const
Get value by key and type.
Definition CCSDSConfig.h:20
@ INVALID_DATA
Data is invalid.
Definition CCSDSResult.h:24
@ INVALID_HEADER_DATA
Header data is invalid.
Definition CCSDSResult.h:25
@ CONFIG_FILE_ERROR
Configuration file error.
Definition CCSDSResult.h:34
@ INVALID_SECONDARY_HEADER_DATA
Secondary header data is invalid.
Definition CCSDSResult.h:26
ESequenceFlag
Represents the sequence flags used in CCSDS telemetry transfer frames.
Definition CCSDSHeader.h:19
@ UNSEGMENTED
11 Complete packet in a single frame.
Definition CCSDSHeader.h:23
@ FIRST_SEGMENT
01 First segment of a new packet.
Definition CCSDSHeader.h:21
std::uint16_t initialValue
Definition CCSDSPacket.h:37
std::uint16_t polynomial
Definition CCSDSPacket.h:36
std::uint16_t finalXorValue
Definition CCSDSPacket.h:38
Represents the primary header of a CCSDS packet.
Definition CCSDSHeader.h:41