CCSDSPack
C++ Library for CCSDS Space Packet manipulation. i.e. generation, extraction, analisys and more
Loading...
Searching...
No Matches
Functions
exec_encoder.cpp File Reference
#include <unordered_map>
#include <string>
#include <vector>
#include <iostream>
#include <chrono>
#include <iomanip>
#include <locale>
#include <sstream>
#include "CCSDSManager.h"
#include "CCSDSHeader.h"
#include "CCSDSResult.h"
#include "CCSDSUtils.h"
#include "exec_utils.h"
Include dependency graph for exec_encoder.cpp:

Go to the source code of this file.

Functions

void printHelp ()
 This is the source file that holds the execution logic of ccsds_encoder binary file.
 
int main (const int argc, char *argv[])
 

Function Documentation

◆ main()

int main ( const int  argc,
char *  argv[] 
)

Definition at line 63 of file exec_encoder.cpp.

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();
84 if (const auto exp = parseArguments(argc, argv, allowed, args); !exp.has_value()) {
85 std::cerr << "[ Error " << exp.error().code() << " ]: "<< exp.error().message() << std::endl ;
86 return exp.error().code();
87 }
88 // std::cout << "Parsed args:\n";
89 //for (const auto& [k, v] : args) {
90 // std::cout << " " << k << ": " << v << '\n';
91 //}
92 if (args["help"] == "true") {
93 printHelp();
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;
100 printHelp();
101 return ARG_PARSE_ERROR;
102 }
103
104 if (!fileExists(args["input"])) {
105 std::cerr << "[ Error " << ARG_PARSE_ERROR << " ]: " << "Input \"" << args["input"] << "\" does not exist" << std::endl;
106 return ARG_PARSE_ERROR;
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;
113 printHelp();
114 return ARG_PARSE_ERROR;
115 }
116
117 if (args.find("config") == args.end()) {
118 std::cerr << "[ Error " << ARG_PARSE_ERROR << " ]: " << "Config file must be specified" << std::endl;
119 printHelp();
120 return ARG_PARSE_ERROR;
121 }
122
123 if (!fileExists(args["config"])) {
124 std::cerr << "[ Error " << ARG_PARSE_ERROR << " ]: " << "Config \"" << args["config"] << "\" does not exist" << std::endl;
125 return ARG_PARSE_ERROR;
126 }
127 const std::string configFile{args["config"]};
128
129 // prepare template packet
130 customConsole(appName,"reading CCSDS configuration file: " + configFile);
131 Config cfg;
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
139 CCSDS::Header header;
140 uint8_t versionNumber;
141 uint8_t type;
142 uint8_t APID;
143 uint8_t dataFieldHeaderFlag;
144 uint16_t sequenceCount;
145 CCSDS::ESequenceFlag sequenceFlag;
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")) {
152 std::cerr << "[ Error " << CONFIG_MISSING_PARAMETER << " ]: " << "Config: Missing int field: ccsds_version_number"
153 << std::endl;
155 }
156 ASSIGN_OR_PRINT(versionNumber, cfg.get<int>("ccsds_version_number"));
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 }
166 ASSIGN_OR_PRINT(type, cfg.get<bool>("ccsds_type"));
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 }
176 ASSIGN_OR_PRINT(dataFieldHeaderFlag, cfg.get<bool>("ccsds_data_field_header_flag"));
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 }
186 ASSIGN_OR_PRINT(APID, cfg.get<int>("ccsds_APID"));
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 }
196 ASSIGN_OR_PRINT(segmented, cfg.get<bool>("ccsds_segmented"));
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
211 ASSIGN_OR_PRINT(dataFieldSize, cfg.get<int>("data_field_size"));
212 ASSIGN_OR_PRINT(syncPatternEnable, cfg.get<bool>("sync_pattern_enable"));
213
214 { // optional definition of sync pattern
215 if (auto exp = cfg.get<int>("sync_pattern"); exp.has_value()) {
216 syncPattern = exp.value();
217 }
218 }
219
220 customConsole(appName,"creating CCSDS template packet");
221 if (segmented) {
222 sequenceCount = 1;
224 }else {
225 sequenceCount = 0;
227 }
228
229 header.setVersionNumber(versionNumber);
230 header.setType(type);
231 header.setAPID(APID);
232 header.setDataFieldHeaderFlag(dataFieldHeaderFlag);
233 header.setSequenceFlags(sequenceFlag);
234 header.setSequenceCount(sequenceCount);
235
236 CCSDS::Packet templatePacket;
237 templatePacket.setPrimaryHeader(header);
238
239 CCSDS::Manager manager;
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 }
244 manager.setDatFieldSize(dataFieldSize);
245 manager.setSyncPatternEnable(syncPatternEnable);
246 if (syncPatternEnable && cfg.isKey("sync_pattern")) {
247 manager.setSyncPattern(syncPattern);
248 }
249 std::vector<uint8_t> inputBytes;
250
251 customConsole(appName,"reading data from " + input);
252 if (const auto exp = readBinaryFile(input); !exp.has_value()) {
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 ;
260 return INVALID_INPUT_DATA;
261 }
262 }
263 customConsole(appName, "generating CCSDS packets using input data");
264 if (const auto exp = manager.setApplicationData(inputBytes); !exp.has_value()) {
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:");
269 if (verbose) printPackets(manager);
270
271 customConsole(appName,"serializing CCSDS packets");
272 auto packets = manager.getPacketsBuffer();
273 customConsole(appName,"writing data to " + output);
274 if (const auto exp = writeBinaryFile(packets, output); !exp.has_value()) {
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]");
282 customConsole(appName,"[ Exit code 0 ]");
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 the decomposition and manipulation of CCSDS primary headers.
Definition CCSDSHeader.h:80
void setVersionNumber(const uint8_t &value)
3 bits
void setSequenceCount(const uint16_t &value)
14 bits
void setSequenceFlags(const uint8_t &value)
2 bits
void setAPID(const uint16_t &value)
11 bits
void setDataFieldHeaderFlag(const uint8_t &value)
1 bits
void setType(const uint8_t &value)
1 bits
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.
Definition CCSDSPacket.h:60
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.
Definition CCSDSUtils.h:145
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 CCSDSUtils.h:154
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
Definition exec_utils.h:11
@ ARG_PARSE_ERROR
Error Parsing argument.
Definition exec_utils.h:10
@ INVALID_INPUT_DATA
Definition exec_utils.h:12
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.
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
Here is the call graph for this function:

◆ printHelp()

void printHelp ( )

This is the source file that holds the execution logic of ccsds_encoder binary file.

Definition at line 21 of file exec_encoder.cpp.

21 {
22 // ascii art generated on https://www.asciiart.eu/text-to-ascii-art
23 // with ANSI SHADOW Font, with 80 and Block frame
24 std::cout << std::endl <<
25 "▐▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▌\n"
26 "▐ ██████╗ ██████╗███████╗██████╗ ███████╗ ▌\n"
27 "▐ ██╔════╝██╔════╝██╔════╝██╔══██╗██╔════╝ ▌\n"
28 "▐ ██║ ██║ ███████╗██║ ██║███████╗ ▌\n"
29 "▐ ██║ ██║ ╚════██║██║ ██║╚════██║ █▀█░█▀█░█▀▀░█░█░ ▌\n"
30 "▐ ╚██████╗╚██████╗███████║██████╔╝███████║ █▀▀░█▀█░█░░░█▀▄░ ▌\n"
31 "▐ ╚═════╝ ╚═════╝╚══════╝╚═════╝ ╚══════╝ ▀░░░▀░▀░▀▀▀░▀░▀░ ▌\n"
32 "▐ ███████╗███╗ ██╗ ██████╗ ██████╗ ██████╗ ███████╗██████╗ ▌\n"
33 "▐ ██╔════╝████╗ ██║██╔════╝██╔═══██╗██╔══██╗██╔════╝██╔══██╗ ▌\n"
34 "▐ █████╗ ██╔██╗ ██║██║ ██║ ██║██║ ██║█████╗ ██████╔╝ ▌\n"
35 "▐ ██╔══╝ ██║╚██╗██║██║ ██║ ██║██║ ██║██╔══╝ ██╔══██╗ ▌\n"
36 "▐ ███████╗██║ ╚████║╚██████╗╚██████╔╝██████╔╝███████╗██║ ██║ ▌\n"
37 "▐ ╚══════╝╚═╝ ╚═══╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝ ▌\n"
38 "▐▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▌\n"
39 << std::endl;
40 std::cout << "Usage: ccsds_encoder [OPTIONS] - take a file and packets it into ccsds packets and saves it to a binary file." << std::endl;
41 std::cout << "Mandatory parameters:" << std::endl;
42 std::cout << " -i or --input <filename> : input file to be encoded" << std::endl;;
43 std::cout << " -o or --output <filename> : Generated output file" << std::endl;;
44 std::cout << " -c or --config <filename> : Configuration file" << std::endl;
45 std::cout << std::endl;
46 std::cout << "Optionals:" << std::endl;
47 std::cout << " -h or --help : Show this help and message" << std::endl;
48 std::cout << " -v or --verbose : Show generated packets information" << std::endl;
49 std::cout << std::endl;
50 std::cout << "Template override: the template CCSDS packet read from the config file" << std::endl;
51 std::cout << "can be overwritten by using the following options. In the case not all" << std::endl;
52 std::cout << "parameters are used, the remaining parameters will be read from the" << std::endl;
53 std::cout << "configuration file." << std::endl;
54 std::cout << " -tv <int> : Template CCSDS version number (3 bits)" << std::endl;
55 std::cout << " -tt <bool> : Template CCSDS Type" << std::endl;
56 std::cout << " -ta <int> : Template CCSDS APID (11 bita)" << std::endl;
57 std::cout << " -th <bool> : Template CCSDS Secondary header presence" << std::endl;
58 std::cout << " -ts <bool> : Template CCSDS Segmented" << std::endl;
59 std::cout << std::endl;
60 std::cout << "For further information please visit: https://github.com/ExoSpaceLabs/CCSDSPack" << std::endl;
61}
Here is the caller graph for this function: