63 {
64 std::string appName = "ccsds_encoder";
65
66 std::unordered_map<std::string, std::string> allowed;
67 allowed.insert({"h", "help"});
68 allowed.insert({"v", "verbose"});
69 allowed.insert({"i", "input"});
70 allowed.insert({"o", "output"});
71 allowed.insert({"c", "config"});
72
73 allowed.insert({"tv", "version_number"});
74 allowed.insert({"tt", "type"});
75 allowed.insert({"ta", "apid"});
76 allowed.insert({"th", "secondary_header"});
77 allowed.insert({"ts", "segmented"});
78
79 std::unordered_map<std::string, std::string> args;
80 args.insert({"verbose", "false"});
81 args.insert({"help", "false"});
82
83 const auto start = std::chrono::high_resolution_clock::now();
85 std::cerr << "[ Error " << exp.error().code() << " ]: "<< exp.error().message() << std::endl ;
86 return exp.error().code();
87 }
88
89
90
91
92 if (args["help"] == "true") {
94 return 0;
95 }
96 bool verbose{args["verbose"] == "true"};
97
98 if (args.find("input") == args.end()) {
99 std::cerr <<
"[ Error " <<
ARG_PARSE_ERROR <<
" ]: " <<
"Input file must be specified" << std::endl;
102 }
103
105 std::cerr <<
"[ Error " <<
ARG_PARSE_ERROR <<
" ]: " <<
"Input \"" << args[
"input"] <<
"\" does not exist" << std::endl;
107 }
108 const std::string input{args["input"]};
109 const std::string output{args["output"]};
110
111 if (output.empty()) {
112 std::cerr <<
"[ Error " <<
ARG_PARSE_ERROR <<
" ]: " <<
"Output file must be specified" << std::endl;
115 }
116
117 if (args.find("config") == args.end()) {
118 std::cerr <<
"[ Error " <<
ARG_PARSE_ERROR <<
" ]: " <<
"Config file must be specified" << std::endl;
121 }
122
124 std::cerr <<
"[ Error " <<
ARG_PARSE_ERROR <<
" ]: " <<
"Config \"" << args[
"config"] <<
"\" does not exist" << std::endl;
126 }
127 const std::string configFile{args["config"]};
128
129
130 customConsole(appName,
"reading CCSDS configuration file: " + configFile);
132 {
133 if (
auto exp = cfg.
load(configFile); !exp.has_value()) {
134 std::cerr << "[ Error " << exp.error().code() << " ]: "<< exp.error().message() << std::endl ;
135 return exp.error().code();
136 }
137 }
138
140 uint8_t versionNumber;
141 uint8_t type;
142 uint8_t APID;
143 uint8_t dataFieldHeaderFlag;
144 uint16_t sequenceCount;
146 uint16_t dataFieldSize;
147 bool segmented;
148 bool syncPatternEnable;
149 uint32_t syncPattern;
150 if (args.find("version_number") == args.end()) {
151 if (!cfg.
isKey(
"ccsds_version_number")) {
153 << std::endl;
155 }
157 }else {
158 versionNumber = std::stoi(args["version_number"]);
159 }
160
161 if (args.find("type") == args.end()) {
162 if (!cfg.
isKey(
"ccsds_type")) {
163 std::cerr <<
"[ Error " <<
CONFIG_MISSING_PARAMETER <<
" ]: " <<
"Config: Missing bool field: ccsds_type" << std::endl;
165 }
167 }else {
168 type = args["type"] == "true";
169 }
170
171 if (args.find("secondary_header") == args.end()) {
172 if (!cfg.
isKey(
"ccsds_data_field_header_flag")) {
173 std::cerr <<
"[ Error " <<
CONFIG_MISSING_PARAMETER <<
" ]: " <<
"Config: Missing bool field: ccsds_data_field_header_flag" << std::endl;
175 }
177 }else {
178 dataFieldHeaderFlag = args["secondary_header"] == "true";
179 }
180
181 if (args.find("apid") == args.end()) {
182 if (!cfg.
isKey(
"ccsds_APID")) {
183 std::cerr <<
"[ Error " <<
CONFIG_MISSING_PARAMETER <<
" ]: " <<
"Config: Missing int field: ccsds_APID" << std::endl;
185 }
187 }else {
188 APID = std::stoi(args["apid"]);
189 }
190
191 if (args.find("segmented") == args.end()) {
192 if (!cfg.
isKey(
"ccsds_segmented")) {
193 std::cerr <<
"[ Error " <<
CONFIG_MISSING_PARAMETER <<
" ]: " <<
"Config: Missing bool field: ccsds_segmented" << std::endl;
195 }
197 }else {
198 segmented = args["segmented"] == "true";
199 }
200
201 if (!cfg.
isKey(
"data_field_size")) {
202 std::cerr <<
"[ Error " <<
CONFIG_MISSING_PARAMETER <<
" ]: " <<
"Config: Missing int field: data_field_size" << std::endl;
204 }
205
206 if (!cfg.
isKey(
"sync_pattern_enable")) {
207 std::cerr <<
"[ Error " <<
CONFIG_MISSING_PARAMETER <<
" ]: " <<
"Config: Missing int field: sync_pattern_enable" << std::endl;
209 }
210
213
214 {
215 if (
auto exp = cfg.
get<
int>(
"sync_pattern"); exp.has_value()) {
216 syncPattern = exp.value();
217 }
218 }
219
221 if (segmented) {
222 sequenceCount = 1;
224 }else {
225 sequenceCount = 0;
227 }
228
235
238
240 if (
const auto exp = manager.
setPacketTemplate(templatePacket); !exp.has_value()) {
241 std::cerr << "[ Error " << exp.error().code() << " ]: "<< exp.error().message() << std::endl ;
242 return exp.error().code();
243 }
246 if (syncPatternEnable && cfg.
isKey(
"sync_pattern")) {
248 }
249 std::vector<uint8_t> inputBytes;
250
253 std::cerr << "[ Error " << exp.error().code() << " ]: "<< exp.error().message() << std::endl ;
254 return exp.error().code();
255 }else {
256 inputBytes = exp.value();
257 if (!segmented && inputBytes.size() > dataFieldSize){
258 std::cerr <<
"[ Error " <<
INVALID_INPUT_DATA <<
" ]: "<<
"Input data is too big for unsegmented packets, data "
259 << inputBytes.size() << " must be less than defined data packet length of " << dataFieldSize << std::endl ;
261 }
262 }
263 customConsole(appName,
"generating CCSDS packets using input data");
265 std::cerr << "[ Error " << exp.error().code() << " ]: "<< exp.error().message() << std::endl ;
266 return exp.error().code();
267 }
268 if (verbose)
customConsole(appName,
"printing data to screen:");
270
275 std::cerr << "[ Error " << exp.error().code() << " ]: "<< exp.error().message() << std::endl ;
276 return exp.error().code();
277 }
278
279 const auto end = std::chrono::high_resolution_clock::now();
280 const auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
281 customConsole(appName,
"execution time: " + std::to_string(duration.count()) +
" [us]");
283 return 0;
284}
#define ASSIGN_OR_PRINT(var, result)
Macro to assign a result value or print an error message.
bool fileExists(const std::string &fileName)
filesystem check fore file existence prepared for both windows and linux.
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< uint8_t > &data, const std::string &filename)
This function takes in a buffer of data and a file name.
void printPackets(CCSDS::Manager &manager)
Prints to console a series of CCSDS Packets contained in the manager.
Manages CCSDS packets and their templates.
ResultBool setPacketTemplate(Packet packet)
Sets a new packet template.
std::vector< uint8_t > getPacketsBuffer() const
Retrieves a buffer containing all the stored packets sequentially.
void setDatFieldSize(uint16_t size)
Sets the size of the data field.
void setSyncPatternEnable(bool enable)
enable sync pattern utilization both in serialization, deserialization, read and write.
ResultBool setApplicationData(const std::vector< uint8_t > &data)
Sets the application data for the packet.
void setSyncPattern(uint32_t syncPattern)
set sync pattern that should indicate the start of a CCSDS packet.
Represents a CCSDS (Consultative Committee for Space Data Systems) packet.
void setPrimaryHeader(PrimaryHeader data)
Sets the primary header using the provided PrimaryHeader object.
bool has_value() const
Checks if the result contains a valid value.
Parses and stores config values from custom file format.
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.
void printHelp()
This is the source file that holds the execution logic of ccsds_encoder binary file.
void customConsole(const std::string &appName, const std::string &message, const std::string &logLevel="INFO")
@ CONFIG_MISSING_PARAMETER
@ ARG_PARSE_ERROR
Error Parsing argument.
CCSDS::ResultBool parseArguments(int argc, char *argv[], std::unordered_map< std::string, std::string > &allowedMap, std::unordered_map< std::string, std::string > &outArgs)
This is the source file that holds the execution logic of ccsds_encoder binary file.
ESequenceFlag
Represents the sequence flags used in CCSDS telemetry transfer frames.
@ UNSEGMENTED
11 Complete packet in a single frame.
@ FIRST_SEGMENT
01 First segment of a new packet.