CCSDSPack
C++ Library for CCSDS Space Packet manipulation. i.e. generation, extraction, analisys and more
Loading...
Searching...
No Matches
Functions
exec_validator.cpp File Reference
#include <unordered_map>
#include <string>
#include <vector>
#include <iostream>
#include <chrono>
#include <fstream>
#include <sstream>
#include "CCSDSPack.h"
#include "exec_utils.h"
#include "../test/inc/TestManager.h"
Include dependency graph for exec_validator.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.
 
std::string printReport (const std::vector< bool > &report, bool &result, const bool validateAgainstTemplate)
 Returns a report of performed validation checks in a string format.
 
void stripAnsiCodes (std::string &input)
 
int main (const int argc, char *argv[])
 

Function Documentation

◆ main()

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

Definition at line 108 of file exec_validator.cpp.

108 {
109 std::string appName = "ccsds_validator";
110
111 std::unordered_map<std::string, std::string> allowed;
112 allowed.insert({"h", "help"});
113 allowed.insert({"v", "verbose"});
114 allowed.insert({"i", "input"});
115 allowed.insert({"c", "config"});
116 allowed.insert({"p", "print-packets"});
117
118 const std::set<std::string> booleanArgs{"verbose", "help", "print-packets"};
119
120 std::unordered_map<std::string, std::string> args;
121 args.insert({"verbose", "false"});
122 args.insert({"print", "false"});
123 args.insert({"print-packets", "false"});
124
125 const auto start = std::chrono::high_resolution_clock::now();
126 if (const auto res = parseArguments(argc, argv, allowed, args, booleanArgs); !res.has_value()) {
127 std::cerr << "[ Error " << res.error().code() << " ]: "<< res.error().message() << std::endl ;
128 return res.error().code();
129 }
130 // std::cout << "Parsed args:\n";
131 //for (const auto& [k, v] : args) {
132 // std::cout << " " << k << ": " << v << '\n';
133 //}
134 if (args["help"] == "true") {
135 printHelp();
136 return 0;
137 }
138 bool verbose{args["verbose"] == "true"};
139
140 if (args.find("input") == args.end()) {
141 std::cerr << "[ Error " << ARG_PARSE_ERROR << " ]: " << "Input file must be specified" << std::endl;
142 printHelp();
143 return ARG_PARSE_ERROR;
144 }
145
146 if (!fileExists(args["input"])) {
147 std::cerr << "[ Error " << ARG_PARSE_ERROR << " ]: " << "Input \"" << args["input"] << "\" does not exist" << std::endl;
148 return ARG_PARSE_ERROR;
149 }
150 const std::string input{args["input"]};
151
152 CCSDS::Manager manager;
153 CCSDS::Validator validator;
154 std::vector<uint8_t> inputBytes;
155 bool isConfigProvided{false};
156
157 manager.setAutoValidateEnable(false);
158 manager.setDataFieldSize(64*1023 ); // 1M Bytes * packet
159 manager.setAutoUpdateEnable(false);
160 customConsole(appName,"reading data from " + input);
161 if (const auto res = readBinaryFile(input); !res.has_value()) {
162 std::cerr << "[ Error " << res.error().code() << " ]: "<< res.error().message() << std::endl ;
163 return res.error().code();
164 }else {
165 inputBytes = res.value();
166 }
167
168 customConsole(appName, "deserializing CCSDS packets from file");
169 if (const auto res = manager.load(inputBytes); !res.has_value()) {
170 std::cerr << "[ Error " << res.error().code() << " ]: "<< res.error().message() << std::endl ;
171 return res.error().code();
172 }
173
174 // config argument specified
175 if (args.find("config") != args.end()) {
176 isConfigProvided = true;
177 if (!fileExists(args["config"])) {
178 std::cerr << "[ Error " << ARG_PARSE_ERROR << " ]: " << "Config \"" << args["config"] << "\" does not exist" << std::endl;
179 return ARG_PARSE_ERROR;
180 }
181 const std::string configFile{args["config"]};
182
183 // prepare template packet
184 customConsole(appName,"reading CCSDS configuration file: " + configFile);
185 Config cfg;
186
187 {
188 if (auto res = cfg.load(configFile); !res.has_value()) {
189 std::cerr << "[ Error " << res.error().code() << " ]: "<< res.error().message() << std::endl ;
190 return res.error().code();
191 }
192 }
193 CCSDS::Packet templatePacket;
194 templatePacket.loadFromConfig(cfg);
195 validator.setTemplatePacket(templatePacket);
196 validator.configure(true,true,true);
197 }// end if config provided
198
199 validator.configure(true,true,false);
200
201 if (verbose) customConsole(appName,"printing data to screen:");
202
203 std::vector<std::vector<bool>> reports;
204 std::string reportsStream;
205 bool overallResult{true};
206 std::int32_t packetIndex{1};
207 std::vector<int> failedPackets;
208 const bool printPackets{args["print-packets"] == "true"};
209
210 for (auto &packet : manager.getPackets()) {
211 if (verbose) std::cout << "[ CCSDS VALIDATOR ] Printing Packet [ " << packetIndex << " ]: " << std::endl;
212 reportsStream += "[ CCSDS VALIDATOR ] Packet report for id: [ " + std::to_string(packetIndex) + " ]\n";
213 if (printPackets) printPacket(packet);
214 validator.validate(packet);
215 auto report = validator.getReport();
216 reports.emplace_back(report);
217 bool currentResult{false};
218 std::string appendReport = printReport(report,currentResult, isConfigProvided);
219 overallResult = overallResult && currentResult;
220 reportsStream += appendReport;
221 if (verbose) std::cout << appendReport << std::endl;
222 if (verbose) std::cout << "[ CCSDS VALIDATOR ] Packet Result [ ";
223 if (verbose && currentResult) std::cout << GREEN;
224 else if (verbose) {
225 std::cout << RED;
226 }
227 if (verbose && currentResult) std::cout << "PASSED" ;
228 else if (verbose) {
229 std::cout << "FAILED";
230 }
231 if (verbose) std::cout << RESET << " ]" << std::endl;
232 if (!currentResult) failedPackets.push_back(packetIndex);
233 packetIndex++;
234 }
235
236 if (!failedPackets.empty() && verbose) {
237 std::string failedPacketsStream;
238 failedPacketsStream = "[ CCSDS VALIDATOR ] Packets failed validation: [ ";
239 for (const auto& packetID : failedPackets) {
240 failedPacketsStream += std::to_string(packetID) + " ";
241 }
242 failedPacketsStream += "]\n" ;
243 std::cout << failedPacketsStream << std::endl;
244 reportsStream += failedPacketsStream;
245 }
246 std::string resultString = (overallResult) ? GREEN + "PASSED" + RESET : RED + "FAILED" + RESET;
247 reportsStream += "[ CCSDS VALIDATOR ] Packets validation [" + resultString + "]";
248 customConsole(appName,"Packets validation [" + resultString + "]");
249
250
251 const auto end = std::chrono::high_resolution_clock::now();
252 const auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
253 customConsole(appName,"execution time: " + std::to_string(duration.count()) + " [us]");
254 if (!overallResult) {
255 customConsole(appName,"[ Exit code 18 ]");
257 }
258 customConsole(appName,"[ Exit code 0 ]");
259 return 0;
260}
bool fileExists(const std::string &fileName)
filesystem check fore file existence prepared for both windows and linux.
void printPacket(CCSDS::Packet &packet)
Prints to console a CCSDS Packets, breaking it down to Primary header and Data field.
CCSDS::ResultBuffer readBinaryFile(const std::string &filename)
Read a specified binary file and return its contents as a buffer.
void printPackets(CCSDS::Manager &manager)
Prints to console a series of CCSDS Packets contained in the manager.
Manages CCSDS packets and their templates.
ResultBool load(const std::vector< Packet > &packets)
Load a vector of packets.
void setAutoUpdateEnable(bool enable)
Enables or disables automatic updates for packets.
void setDataFieldSize(std::uint16_t size)
Sets the size of the data field.
void setAutoValidateEnable(bool enable)
Enables or disables automatic validation of packets.
Represents a CCSDS (Consultative Committee for Space Data Systems) packet.
Definition CCSDSPacket.h:59
ResultBool loadFromConfig(const Config &cfg)
Loads a packet from a configuration object, including secondary header if present.
bool has_value() const
Checks if the result contains a valid value.
Handles validation of CCSDS packets.
std::vector< bool > getReport() const
Returns a report of performed validation checks.
void configure(bool validatePacketCoherence, bool validateSequenceCount, bool validateAgainstTemplate)
Configures validation options.
void setTemplatePacket(const Packet &templatePacket)
Sets the template packet for validation.
bool validate(const Packet &packet)
Validates a given packet.
Parses and stores config values from custom file format.
Definition CCSDSConfig.h:11
CCSDS::ResultBool load(const std::string &filename)
Load config file.
void customConsole(const std::string &appName, const std::string &message, const std::string &logLevel="INFO")
Prints log to console adding various information about.
CCSDS::ResultBool parseArguments(int argc, char *argv[], std::unordered_map< std::string, std::string > &allowedMap, std::unordered_map< std::string, std::string > &outArgs, const std::set< std::string > &booleanArgs)
Parses the input arguments with defined values returns an unordered map with given keys and input val...
@ PACKET_VALIDATION_FAILED
Definition exec_utils.h:16
@ ARG_PARSE_ERROR
Error Parsing argument.
Definition exec_utils.h:12
void printHelp()
This is the source file that holds the execution logic of ccsds_encoder binary file.
std::string printReport(const std::vector< bool > &report, bool &result, const bool validateAgainstTemplate)
Returns a report of performed validation checks in a string format.
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 18 of file exec_validator.cpp.

18 {
19 // ascii art generated on https://www.asciiart.eu/text-to-ascii-art
20 // with ANSI SHADOW Font, with 80 and Block frame
21 std::cout << std::endl <<
22 "▐▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▌\n"
23 "▐ ██████╗ ██████╗███████╗██████╗ ███████╗ ▌\n"
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 << std::endl;
37 std::cout << "Usage: ccsds_validator [OPTIONS] - take a binary file holding CCSDS packets and validates it." << std::endl;
38 std::cout << "Mandatory parameters:" << std::endl;
39 std::cout << " -i or --input <filename> : input file to be encoded" << std::endl;;
40 std::cout << std::endl;
41 std::cout << "Optionals:" << std::endl;
42 std::cout << " -c or --config <filename> : Configuration file" << std::endl;
43 std::cout << " -h or --help : Show this help and message" << std::endl;
44 std::cout << " -v or --verbose : Show packet specific report" << std::endl;
45 std::cout << " -p or --print-packets : Show generated packets information" << std::endl;
46 std::cout << std::endl;
47 std::cout << "Note : If config file is provided, the loaded packets are validated against the the template packet." << std::endl;
48 std::cout << std::endl;
49 std::cout << "For further information please visit: https://github.com/ExoSpaceLabs/CCSDSPack" << std::endl;
50}
Here is the caller graph for this function:

◆ printReport()

std::string printReport ( const std::vector< bool > &  report,
bool &  result,
const bool  validateAgainstTemplate 
)

Returns a report of performed validation checks in a string format.

  • Packet Coherence:
    • index [0]: Data Field Length Header declared equals actual data field length
    • index [1]: CRC15 value declared equals calculated CRC16 of the data field
    • index [2]: Sequence Control flags and count coherence
    • index [3]: Sequence Control count coherence (incremental start from 1)
  • Compare Against Template:
    • index [4]: Identification and Version in packet matches template
    • index [5]: Template Sequence Control match
Returns
A vector of boolean results for each performed check.

Definition at line 66 of file exec_validator.cpp.

66 {
67
68 std::string packetReport = " [REPORT] Data Field Length and Primary Header : ";
69 packetReport += (report[0]) ? GREEN + "Passed\n" + RESET : RED + "failed\n" + RESET;
70 packetReport += " [REPORT] CRC15 value coherence : " ;
71 packetReport += (report[1]) ? GREEN + "Passed\n" + RESET : RED + "failed\n" + RESET;
72 packetReport += " [REPORT] Sequence Control flags and count coherence : " ;
73 packetReport += (report[2]) ? GREEN + "Passed\n" + RESET : RED + "failed\n" + RESET;
74 packetReport += " [REPORT] Sequence Control count coherence : " ;
75 packetReport += (report[3]) ? GREEN + "Passed\n" + RESET : RED + "failed\n" + RESET;
76
77 result = report[0] && report[1] && report[2] && report[3];
78 if (validateAgainstTemplate){
79 packetReport += " [REPORT] Identification and Version : " ;
80 packetReport += (report[4]) ? GREEN + "Passed\n" + RESET : RED + "failed\n" + RESET;
81 packetReport += " [REPORT] Template Sequence Control : " ;
82 packetReport += (report[5]) ? GREEN + "Passed\n" + RESET : RED + "failed\n" + RESET;
83 result = result && report[4] && report[5];
84 }
85 return packetReport;
86}
Here is the caller graph for this function:

◆ stripAnsiCodes()

void stripAnsiCodes ( std::string &  input)

Definition at line 88 of file exec_validator.cpp.

88 {
89 std::string output;
90 output.reserve(input.size()); // Avoids reallocations
91
92 for (size_t i = 0; i < input.size(); ) {
93 if (input[i] == '\033' && i + 1 < input.size() && input[i + 1] == '[') {
94 // Skip ANSI escape sequence
95 i += 2;
96 while (i < input.size() && (input[i] < '@' || input[i] > '~')) {
97 ++i;
98 }
99 if (i < input.size()) ++i; // skip final 'm' or other final char
100 } else {
101 output += input[i++];
102 }
103 }
104
105 input = std::move(output);
106}