CCSDSPack
C++ Library for CCSDS Space Packet manipulation. i.e. generation, extraction, analisys and more
Loading...
Searching...
No Matches
CCSDSManager.cpp
Go to the documentation of this file.
1// Copyright 2025-2026 ExoSpaceLabs
2// SPDX-License-Identifier: Apache-2.0
3
4#include <random>
5#include <utility>
6#include <algorithm>
7#include "CCSDSManager.h"
8#include "CCSDSUtils.h"
9
10void CCSDS::Manager::setSyncPattern(std::uint32_t syncPattern) { m_syncPattern = syncPattern; }
11
12uint32_t CCSDS::Manager::getSyncPattern() const { return m_syncPattern; }
13
14void CCSDS::Manager::setSyncPatternEnable(const bool enable) { m_syncPattEnable = enable; }
15
16bool CCSDS::Manager::getSyncPatternEnable() const { return m_syncPattEnable; }
17
19 RET_IF_ERR_MSG(m_templateIsSet, ErrorCode::TEMPLATE_SET_FAILURE, "Cannot set Template as it is already set, please clear Manager first");
20 m_templatePacket.setUpdatePacketEnable(false);
21 m_templatePacket = std::move(packet);
22 m_validator.setTemplatePacket(m_templatePacket);
23 m_validator.configure(true, true, true);
24 m_validateEnable = true;
25 m_templateIsSet = true;
26 return true;
27}
28
30
31 Packet templatePacket;
32 FORWARD_RESULT(templatePacket.loadFromConfigFile(configPath));
33 m_templatePacket = std::move(templatePacket);
34 m_templateIsSet = true;
35 return true;;
36}
37#ifndef CCSDS_MCU
39
40 Packet templatePacket;
41 FORWARD_RESULT(templatePacket.loadFromConfig(cfg));
42 m_templatePacket = std::move(templatePacket);
43 m_templateIsSet = true;
44 return true;;
45}
46#endif
47void CCSDS::Manager::setDataFieldSize(const std::uint16_t size) {
48 m_templatePacket.setDataFieldSize(size);
49}
50
52 return m_templatePacket.getDataFieldMaximumSize();
53}
54
55CCSDS::ResultBool CCSDS::Manager::setApplicationData(const std::vector<std::uint8_t> &data) {
56 RET_IF_ERR_MSG(data.empty(), ErrorCode::NO_DATA, "Cannot set Application data, Provided data is empty");
57 RET_IF_ERR_MSG(!m_templateIsSet, ErrorCode::INVALID_HEADER_DATA, "Cannot set Application data, No template has been set");
58
59 const auto maxBytesPerPacket = m_templatePacket.getDataFieldMaximumSize();
60 const auto dataBytesSize = data.size();
61
62 if (!m_packets.empty()) {
63 m_packets.clear();
64 }
65
66 std::uint32_t i = 0;
67 auto remainderBytes = static_cast<std::int32_t>(dataBytesSize);
68 auto sequenceFlag = UNSEGMENTED;
69 while (i < dataBytesSize) {
70 Packet newPacket = m_templatePacket;
71 std::vector<std::uint8_t> tmp;
72 if (remainderBytes > maxBytesPerPacket) {
73 tmp.insert(tmp.end(), data.begin() + i, data.begin() + i + maxBytesPerPacket);
74 remainderBytes -= maxBytesPerPacket;
75 if (i == 0) {
76 sequenceFlag = FIRST_SEGMENT;
77 m_sequenceCount++;
78 } else {
79 sequenceFlag = CONTINUING_SEGMENT;
80 }
81 i += maxBytesPerPacket;
82 FORWARD_RESULT(newPacket.setApplicationData(tmp));
83 newPacket.setSequenceFlags(sequenceFlag);
84 FORWARD_RESULT(newPacket.setSequenceCount(m_sequenceCount));
85 } else {
86 tmp.insert(tmp.end(), data.begin() + i, data.begin() + i + remainderBytes);
87 i += remainderBytes;
88 if (sequenceFlag != UNSEGMENTED) {
90 FORWARD_RESULT(newPacket.setSequenceCount(m_sequenceCount));
91 }
92 FORWARD_RESULT(newPacket.setApplicationData(tmp));
93 }
94 newPacket.setUpdatePacketEnable(m_updateEnable);
95 m_packets.push_back(std::move(newPacket));
96 m_sequenceCount++;
97 }
98 return true;
99}
100
101void CCSDS::Manager::setAutoUpdateEnable(const bool enable) {
102 m_updateEnable = enable;
103 for (auto &packet: m_packets) {
104 packet.setUpdatePacketEnable(enable);
105 }
106}
107
109 m_validateEnable = enable;
110}
111
113 auto data = m_templatePacket.serialize();
114 RET_IF_ERR_MSG(data.empty(), ErrorCode::NO_DATA, "Cannot get Packet template data, data is empty (impossible)"); // possibly redundant.
115 return data;
116}
117
119 RET_IF_ERR_MSG(index < 0 || index >= m_packets.size(), ErrorCode::INVALID_DATA,
120 "Cannot get packet, index is out of bounds");
121 if (m_validateEnable) {
122 m_packets[index].update();
123 const std::string errorMessage = "Validation failure for packet at index " + std::to_string(index);
124 RET_IF_ERR_MSG(!m_validator.validate(m_packets[index]), ErrorCode::VALIDATION_FAILURE,
125 errorMessage);
126 }
127 return m_packets[index].serialize();
128}
129
130std::vector<std::uint8_t> CCSDS::Manager::getPacketsBuffer() const {
131 std::vector<std::uint8_t> buffer;
132 for (auto packet : m_packets) {
133 if (m_syncPattEnable) {
134 buffer.push_back(m_syncPattern >> 24 & 0xff);
135 buffer.push_back(m_syncPattern >> 16 & 0xff);
136 buffer.push_back(m_syncPattern >> 8 & 0xff);
137 buffer.push_back(m_syncPattern & 0xff);
138 }
139 std::vector<std::uint8_t> packetBuffer = packet.serialize();
140 buffer.insert(buffer.end(), packetBuffer.begin(), packetBuffer.end());
141 }
142 return buffer;
143}
144
146 RET_IF_ERR_MSG(m_packets.empty(), ErrorCode::NO_DATA, "Cannot get Application data, no packets have been set.");
147 std::vector<std::uint8_t> data;
148
149 for (std::uint32_t index = 0; index < m_packets.size(); index++) {
150 if (m_validateEnable) {
151 const std::string errorMessage = "Validation failure for packet at index" + std::to_string(index);
152 RET_IF_ERR_MSG(!m_validator.validate(m_packets[index]), ErrorCode::VALIDATION_FAILURE,
153 errorMessage);
154 }
155 auto applicationData = m_packets[index].getApplicationDataBytes();
156 data.insert(data.end(), applicationData.begin(), applicationData.end());
157 }
158 return data;
159}
160
162 RET_IF_ERR_MSG(index < 0 || index >= m_packets.size(), ErrorCode::INVALID_DATA,
163 "Cannot get Application data, index is out of bounds");
164 return m_packets[index].getApplicationDataBytes();
165}
166
168 return m_packets.size();
169}
170
171std::vector<CCSDS::Packet> CCSDS::Manager::getPackets() {
172 return m_packets;
173}
174
176
177 if (m_validateEnable && !m_updateEnable) {
178 if (!m_templateIsSet) {
179 m_validator.configure(true, true, false);
180 }
181 RET_IF_ERR_MSG(m_validator.validate(packet), ErrorCode::VALIDATION_FAILURE, "packet is not valid");
182 }
183 packet.setUpdatePacketEnable(m_updateEnable);
184 m_packets.push_back(std::move(packet));
185 return true;
186}
187
188CCSDS::ResultBool CCSDS::Manager::addPacketFromBuffer(const std::vector<std::uint8_t>& packetBuffer) {
189 Packet packet;
190 FORWARD_RESULT(packet.deserialize(packetBuffer));
191 FORWARD_RESULT(addPacket(packet));
192 return true;
193}
194
195
196[[nodiscard]] CCSDS::ResultBool CCSDS::Manager::load(const std::vector<Packet>& packets) {
197
198 for (const auto& packet: packets) {
199 FORWARD_RESULT(addPacket(packet));
200 }
201 return true;
202}
203
204[[nodiscard]] CCSDS::ResultBool CCSDS::Manager::load(const std::vector<std::uint8_t>& packetsBuffer) {
205 RET_IF_ERR_MSG(packetsBuffer.size() < 8, ErrorCode::INVALID_DATA, "invalid packet buffer size");
206 std::uint32_t offset{0};
207 while (offset < packetsBuffer.size()) {
208 std::vector<std::uint8_t> headerData;
209 if (m_syncPattEnable) {
210 const std::uint32_t value = (static_cast<std::uint32_t>(packetsBuffer[offset]) << 24) |
211 (static_cast<std::uint32_t>(packetsBuffer[offset+1]) << 16) |
212 (static_cast<std::uint32_t>(packetsBuffer[offset+2]) << 8) |
213 (static_cast<std::uint32_t>(packetsBuffer[offset+3]));
214 RET_IF_ERR_MSG(value != m_syncPattern, ErrorCode::INVALID_DATA, "Sync Pattern mismatch.");
215 offset += 4;
216 }
217 headerData.clear();
218 copy_n(packetsBuffer.begin() + offset, 6, std::back_inserter(headerData));
219 Header header;
220 FORWARD_RESULT( header.deserialize(headerData));
221
222 const std::uint16_t packetSize = header.getDataLength() + 8;
223 std::vector<std::uint8_t>packetData;
224 packetData.clear();
225 copy_n(packetsBuffer.begin() + offset, packetSize, std::back_inserter(packetData));
226 FORWARD_RESULT(addPacketFromBuffer(packetData));
227 offset += packetSize;
228 }
229 return true;
230}
231
232CCSDS::ResultBool CCSDS::Manager::read(const std::string &binaryFile) {
233 std::vector<std::uint8_t> buffer;
234 ASSIGN_CP(buffer, readBinaryFile(binaryFile));
235 FORWARD_RESULT(load(buffer));
236 return true;
237}
238
239CCSDS::ResultBool CCSDS::Manager::write(const std::string& binaryFile) const {
240 FORWARD_RESULT(writeBinaryFile(getPacketsBuffer(),binaryFile));
241 return true;
242}
243
244
246 Packet templatePacket;
247 templatePacket.setUpdatePacketEnable(false);
248 if (stringEndsWith(filename, ".bin")) {
249 std::vector<std::uint8_t> buffer;
250 ASSIGN_CP(buffer, readBinaryFile(filename));
251 FORWARD_RESULT(templatePacket.deserialize(buffer));
252 }else if (stringEndsWith(filename, ".cfg")) {
253 FORWARD_RESULT(templatePacket.loadFromConfigFile(filename));
254 } else {
255 return Error{INVALID_DATA,"Cannot load template, invalid file provided [supported extensions [.bin, .cfg]]"};
256 }
257 FORWARD_RESULT(setPacketTemplate(templatePacket));
258 return true;
259}
260
262 clearPackets();
263 m_templateIsSet = false;
264 m_templatePacket= {};
265}
266
268 m_packets.clear();
269 m_sequenceCount = 0;
270 m_validator.clear();
271}
#define RET_IF_ERR_MSG(condition, errorCode, message)
Macro to return an error with an error message if a condition is met.
#define FORWARD_RESULT(result)
Macro to return a result as-is (for functions returning Result<T>).
#define ASSIGN_CP(var, result)
Macro to assign a result value to a variable or return an error by copy.
bool stringEndsWith(const std::string &str, const std::string &suffix)
Tests if str ends with suffix.
CCSDS::ResultBuffer readBinaryFile(const std::string &filename)
Read a specified binary file and return its contents as a buffer.
CCSDS::ResultBool writeBinaryFile(const std::vector< std::uint8_t > &data, const std::string &filename)
This function takes in a buffer of data and a file name.
Represents an error with both an error code and a message.
Definition CCSDSResult.h:47
Manages the decomposition and manipulation of CCSDS primary headers.
Definition CCSDSHeader.h:83
ResultBool deserialize(const std::vector< std::uint8_t > &data)
Sets the header data from a 64-bit integer representation.
std::uint16_t getDataLength() const
16 bits
Definition CCSDSHeader.h:93
ResultBool loadTemplateConfigFile(const std::string &configPath)
Loads a template packet from a configuration file.
ResultBool setPacketTemplate(Packet packet)
Sets a new packet template.
std::vector< Packet > getPackets()
Retrieves all stored packets.
ResultBuffer getPacketTemplate()
Retrieves the packet template in serialized form.
void setSyncPatternEnable(bool enable)
enable sync pattern utilization both in serialization, deserialization, read and write.
std::uint16_t getDataFieldSize() const
retrieves the set data field size (this includes the secondary header if present)
ResultBool readTemplate(const std::string &filename)
Load a template packet from a binary or configuration file.
void setSyncPattern(std::uint32_t syncPattern)
set sync pattern that should indicate the start of a CCSDS packet.
ResultBool load(const std::vector< Packet > &packets)
Load a vector of packets.
ResultBool addPacket(Packet packet)
Adds a new packet to the list.
std::uint32_t getSyncPattern() const
returns the currently set sync pattern.
std::uint16_t getTotalPackets() const
Retrieves the total number of packets managed.
ResultBuffer getApplicationDataBuffer()
Retrieves the application data from the packets.
std::uint32_t m_syncPattern
ResultBool loadTemplateConfig(const Config &cfg)
Loads a template packet from a configuration object.
ResultBool read(const std::string &binaryFile)
Load a packet or a series of packets from a binary file.
void clearPackets()
Clears the packets and sets the counter to 0.
std::vector< std::uint8_t > getPacketsBuffer() const
Retrieves a buffer containing all the stored packets sequentially.
ResultBool addPacketFromBuffer(const std::vector< std::uint8_t > &packetBuffer)
Adds a new packet to the list.
void setAutoUpdateEnable(bool enable)
Enables or disables automatic updates for packets.
void setDataFieldSize(std::uint16_t size)
Sets the size of the data field.
bool getSyncPatternEnable() const
returns the current settings of the sync pattern enable
ResultBool setApplicationData(const std::vector< std::uint8_t > &data)
Sets the application data for the packet.
void clear()
Clears the manager, removes all packets and template.
void setAutoValidateEnable(bool enable)
Enables or disables automatic validation of packets.
ResultBuffer getApplicationDataBufferAtIndex(std::uint16_t index)
Retrieves the application data from a packet at the given index.
ResultBool write(const std::string &binaryFile) const
Write a packet or a series of packets to a binary file.
ResultBuffer getPacketBufferAtIndex(std::uint16_t index)
Retrieves a packet at the specified index.
Represents a CCSDS (Consultative Committee for Space Data Systems) packet.
Definition CCSDSPacket.h:62
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.
ResultBool loadFromConfig(const Config &cfg)
Loads a packet from a configuration object, including secondary header if present.
void setSequenceFlags(ESequenceFlag flags)
Sets the sequence flags for the packet's primary header.
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.
ResultBool deserialize(const std::vector< std::uint8_t > &data)
Deserializes a vector of bytes into a CCSDS packet.
Encapsulates a result that can hold either a value or an Error.
Definition CCSDSResult.h:85
Parses and stores config values from custom file format.
Definition CCSDSConfig.h:14
@ NO_DATA
No data available.
Definition CCSDSResult.h:26
@ INVALID_DATA
Data is invalid.
Definition CCSDSResult.h:27
@ INVALID_HEADER_DATA
Header data is invalid.
Definition CCSDSResult.h:28
@ TEMPLATE_SET_FAILURE
Failed to set Template Packet.
Definition CCSDSResult.h:34
@ VALIDATION_FAILURE
Validation Failure.
Definition CCSDSResult.h:33
@ LAST_SEGMENT
10 Last segment of a multi-frame packet.
Definition CCSDSHeader.h:25
@ UNSEGMENTED
11 Complete packet in a single frame.
Definition CCSDSHeader.h:26
@ CONTINUING_SEGMENT
00 Intermediate segment of a packet.
Definition CCSDSHeader.h:23
@ FIRST_SEGMENT
01 First segment of a new packet.
Definition CCSDSHeader.h:24