6#include <unordered_map>
23 std::cout << std::endl <<
24 "▐▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▌\n"
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"
39 std::cout <<
"Usage: ccsds_decoder [OPTIONS] - decode a ccsds binary file and generate a file from application data." << std::endl;
40 std::cout <<
"Mandatory parameters:" << std::endl;
41 std::cout <<
" -i or --input <filename> : input file to be encoded" << std::endl;;
42 std::cout <<
" -o or --output <filename> : Generated output file" << std::endl;;
43 std::cout <<
" -c or --config <filename> : Configuration file" << std::endl;
44 std::cout << std::endl;
45 std::cout <<
"Optionals:" << std::endl;
46 std::cout <<
" -h or --help : Show this help and message" << std::endl;
47 std::cout <<
" -v or --verbose : Show generated packets information" << std::endl;
48 std::cout << std::endl;
49 std::cout <<
"Template override: the template CCSDS packet read from the config file" << std::endl;
50 std::cout <<
"can be overwritten by using the following options. In the case not all" << std::endl;
51 std::cout <<
"parameters are used, the remaining parameters will be read from the" << std::endl;
52 std::cout <<
"configuration file." << std::endl;
53 std::cout <<
" -tv <int> : Template CCSDS version number (3 bits)" << std::endl;
54 std::cout <<
" -tt <bool> : Template CCSDS Type" << std::endl;
55 std::cout <<
" -ta <int> : Template CCSDS APID (11 bita)" << std::endl;
56 std::cout <<
" -th <bool> : Template CCSDS Secondary header presence" << std::endl;
57 std::cout <<
" -ts <bool> : Template CCSDS Segmented" << std::endl;
58 std::cout << std::endl;
59 std::cout <<
"For further information please visit: https://github.com/ExoSpaceLabs/CCSDSPack" << std::endl;
62int main(
const int argc,
char* argv[]) {
63 std::string appName =
"ccsds_decoder";
65 std::unordered_map<std::string, std::string> allowed;
66 allowed.insert({
"h",
"help"});
67 allowed.insert({
"v",
"verbose"});
68 allowed.insert({
"i",
"input"});
69 allowed.insert({
"o",
"output"});
70 allowed.insert({
"c",
"config"});
72 allowed.insert({
"tv",
"version_number"});
73 allowed.insert({
"tt",
"type"});
74 allowed.insert({
"ta",
"apid"});
75 allowed.insert({
"th",
"secondary_header"});
76 allowed.insert({
"ts",
"segmented"});
78 std::unordered_map<std::string, std::string> args;
79 args.insert({
"verbose",
"false"});
80 args.insert({
"help",
"false"});
82 const auto start = std::chrono::high_resolution_clock::now();
84 std::cerr <<
"[ Error " << exp.error().code() <<
" ]: "<< exp.error().message() << std::endl ;
85 return exp.error().code();
91 if (args[
"help"] ==
"true") {
95 bool verbose{args[
"verbose"] ==
"true"};
97 if (args.find(
"input") == args.end()) {
98 std::cerr <<
"[ Error " <<
ARG_PARSE_ERROR <<
" ]: " <<
"Input file must be specified" << std::endl;
104 std::cerr <<
"[ Error " <<
ARG_PARSE_ERROR <<
" ]: " <<
"Input \"" << args[
"input"] <<
"\" does not exist" << std::endl;
107 const std::string input{args[
"input"]};
108 const std::string output{args[
"output"]};
110 if (output.empty()) {
111 std::cerr <<
"[ Error " <<
ARG_PARSE_ERROR <<
" ]: " <<
"Output file must be specified" << std::endl;
116 if (args.find(
"config") == args.end()) {
117 std::cerr <<
"[ Error " <<
ARG_PARSE_ERROR <<
" ]: " <<
"Config file must be specified" << std::endl;
123 std::cerr <<
"[ Error " <<
ARG_PARSE_ERROR <<
" ]: " <<
"Config \"" << args[
"config"] <<
"\" does not exist" << std::endl;
126 const std::string configFile{args[
"config"]};
129 customConsole(appName,
"reading CCSDS configuration file: " + configFile);
132 if (
auto exp = cfg.
load(configFile); !exp.has_value()) {
133 std::cerr <<
"[ Error " << exp.error().code() <<
" ]: "<< exp.error().message() << std::endl ;
134 return exp.error().code();
139 uint8_t versionNumber;
142 uint8_t dataFieldHeaderFlag;
143 uint16_t sequenceCount;
145 uint16_t dataFieldSize;
147 bool syncPatternEnable;
148 bool validationEnable;
149 uint32_t syncPattern;
150 if (args.find(
"version_number") == args.end()) {
151 if (!cfg.
isKey(
"ccsds_version_number")) {
158 versionNumber = std::stoi(args[
"version_number"]);
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;
168 type = args[
"type"] ==
"true";
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;
178 dataFieldHeaderFlag = args[
"secondary_header"] ==
"true";
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;
188 APID = std::stoi(args[
"apid"]);
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;
198 segmented = args[
"segmented"] ==
"true";
201 if (!cfg.
isKey(
"validation_enable")) {
202 std::cerr <<
"[ Error " <<
CONFIG_MISSING_PARAMETER <<
" ]: " <<
"Config: Missing bool field: validation_enable" << std::endl;
206 if (!cfg.
isKey(
"data_field_size")) {
207 std::cerr <<
"[ Error " <<
CONFIG_MISSING_PARAMETER <<
" ]: " <<
"Config: Missing int field: data_field_size" << std::endl;
211 if (!cfg.
isKey(
"sync_pattern_enable")) {
212 std::cerr <<
"[ Error " <<
CONFIG_MISSING_PARAMETER <<
" ]: " <<
"Config: Missing int field: sync_pattern_enable" << std::endl;
221 if (
auto exp = cfg.
get<
int>(
"sync_pattern"); exp.has_value()) {
222 syncPattern = exp.value();
248 if (syncPatternEnable && cfg.
isKey(
"sync_pattern")) {
251 std::vector<uint8_t> inputBytes;
255 std::cerr <<
"[ Error " << exp.error().code() <<
" ]: "<< exp.error().message() << std::endl ;
256 return exp.error().code();
258 inputBytes = exp.value();
259 if (!segmented && inputBytes.size() > dataFieldSize){
260 std::cerr <<
"[ Error " <<
INVALID_INPUT_DATA <<
" ]: "<<
"Input data is too big for unsegmented packets, data "
261 << inputBytes.size() <<
" must be less than defined data packet length of " << dataFieldSize << std::endl ;
265 customConsole(appName,
"deserializing CCSDS packets from file");
266 if (
const auto exp = manager.
load(inputBytes); !exp.has_value()) {
267 std::cerr <<
"[ Error " << exp.error().code() <<
" ]: "<< exp.error().message() << std::endl ;
268 return exp.error().code();
270 if (verbose)
customConsole(appName,
"printing loaded packets data to screen:");
273 customConsole(appName,
"retrieving Application data from CCSDS packets");
275 std::vector<uint8_t> outputData;
277 std::cerr <<
"[ Error " << exp.error().code() <<
" ]: "<< exp.error().message() << std::endl ;
278 return exp.error().code();
280 outputData = exp.value();
285 std::cerr <<
"[ Error " << exp.error().code() <<
" ]: "<< exp.error().message() << std::endl ;
286 return exp.error().code();
289 const auto end = std::chrono::high_resolution_clock::now();
290 const auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
291 customConsole(appName,
"execution time: " + std::to_string(duration.count()) +
" [us]");
#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.
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 load(const std::vector< Packet > &packets)
Load a vector of packets.
ResultBuffer getApplicationDataBuffer()
Retrieves the application data from the packets.
void setSyncPattern(uint32_t syncPattern)
set sync pattern that should indicate the start of a CCSDS packet.
void setAutoValidateEnable(bool enable)
Enables or disables automatic validation of packets.
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.
int main(const int argc, char *argv[])
void printHelpDecoder()
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.