LibMISB - Examples - Dynamic metadata
| LibMISB |
|---|
| Introduction |
| Supported Standards |
| Getting Started |
| Examples |
| Evaluating |
| Contact Us |
What This Example Does
misb-changing-metadata.cpp demonstrates a live metadata stream workflow with LibMISB:
- Builds ST0601 JSON metadata on every loop.
- Changes key fields each iteration:
tag 2: UTC timestamp tag 3: mission id (MISSION-100, MISSION-101, ...) tag 4: platform tail (AF-100, AF-101, ...) tag 5: heading-like numeric value
- Encodes JSON to KLV bytes.
- Decodes KLV back to JSON.
- Prints encoded size and decoded JSON so you can verify changing values.
Example source code
/* Copyright (C) 2026 RidgeRun, LLC (http://www.ridgerun.com)
* All Rights Reserved.
*
* The contents of this software are proprietary and confidential to RidgeRun,
* LLC. No part of this program may be photocopied, reproduced or translated
* into another programming language without prior written consent of
* RidgeRun, LLC. The user is free to modify the source code after obtaining
* a software license from RidgeRun. All source code changes must be provided
* back to RidgeRun without any encumbrance.
*/
#include "libmisb/formatter/jsonformatter.hpp"
#include <chrono>
#include <ctime>
#include <iomanip>
#include <iostream>
#include <memory>
#include <sstream>
#include <string>
#include <thread>
#include <libmisb/libmisb.hpp>
namespace {
constexpr char kSt0601Key[] = "060E2B34020B01010E01030101000000";
constexpr unsigned int kDefaultIterations = 20;
constexpr unsigned int kDefaultIntervalMs = 500;
std::string BuildUtcTimestamp() {
auto now = std::chrono::system_clock::now();
auto now_time = std::chrono::system_clock::to_time_t(now);
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
now.time_since_epoch()) %
1000;
std::tm now_tm{};
#if defined(_WIN32)
gmtime_s(&now_tm, &now_time);
#else
gmtime_r(&now_time, &now_tm);
#endif
std::ostringstream stream;
stream << std::put_time(&now_tm, "%b. %d, %Y. %H:%M:%S");
stream << '.' << std::setw(3) << std::setfill('0') << ms.count();
return stream.str();
}
std::string BuildChangingMetadataJson(unsigned int iteration) {
std::ostringstream heading;
heading << std::fixed << std::setprecision(2)
<< static_cast<double>((iteration * 11) % 360);
std::ostringstream mission;
mission << "MISSION-" << (100 + (iteration % 900));
std::ostringstream tail_number;
tail_number << "AF-" << (100 + (iteration % 900));
std::ostringstream json;
json << "{\"key\":\"" << kSt0601Key << "\",\"items\":[";
json << "{\"tag\":\"2\",\"value\":\"" << BuildUtcTimestamp() << "\"},";
json << "{\"tag\":\"3\",\"value\":\"" << mission.str() << "\"},";
json << "{\"tag\":\"4\",\"value\":\"" << tail_number.str() << "\"},";
json << "{\"tag\":\"5\",\"value\":\"" << heading.str() << "\"},";
json << "{\"tag\":\"48\",\"value\":[";
json << "{\"tag\":\"2\",\"value\":\"1\"},";
json << "{\"tag\":\"4\",\"value\":\"TS/SI/CompartmentA//\"}";
json << "]}";
json << "]}";
return json.str();
}
unsigned int ParseUnsignedArgument(const char* value, unsigned int fallback) {
try {
return static_cast<unsigned int>(std::stoul(value));
} catch (...) {
return fallback;
}
}
} // namespace
int main(int argc, char* argv[]) {
unsigned int iterations = kDefaultIterations;
unsigned int interval_ms = kDefaultIntervalMs;
if (argc > 1) {
iterations = ParseUnsignedArgument(argv[1], kDefaultIterations);
}
if (argc > 2) {
interval_ms = ParseUnsignedArgument(argv[2], kDefaultIntervalMs);
}
libmisb::LibMisb libmisb;
libmisb.SetLogLevel(LIBMISB_INFO);
libmisb.SetFormatter(std::make_shared<libmisb::formatter::JsonFormatter>());
const bool run_forever = (iterations == 0);
if (run_forever) {
std::cout << "Running continuously. Metadata changes every loop.\n";
} else {
std::cout << "Running " << iterations
<< " iterations. Metadata changes every loop.\n";
}
for (unsigned int i = 0; run_forever || i < iterations; ++i) {
const std::string json_input = BuildChangingMetadataJson(i);
std::vector<unsigned char> packet = libmisb.Encode(json_input);
if (packet.empty()) {
LOGGER.Log("Failed to encode metadata for current iteration",
LIBMISB_ERROR);
return 1;
}
const std::string decoded_output = libmisb.Decode(packet);
if (decoded_output.empty()) {
LOGGER.Log("Failed to decode packet for current iteration", LIBMISB_ERROR);
return 1;
}
std::cout << "Iteration " << i << " -> encoded bytes: " << packet.size()
<< "\n";
std::cout << "Decoded metadata: " << decoded_output << "\n\n";
std::this_thread::sleep_for(std::chrono::milliseconds(interval_ms));
}
if (!run_forever) {
std::cout << "Finished metadata update loop.\n";
}
return 0;
}
Prerequisites
You need LibMISB built already (or in eval mode), plus its dependencies.
Compile As Standalone External C++ File
This compiles the file from outside the project tree, linking against the already-built LibMISB artifacts.
1) Create misb-changing-metadata.cpp file and copy example source code
2) Compile the application:
g++ misb-changing-metadata.cpp -o misb-changing-metadata-standalone `pkg-config --cflags --libs glib-2.0 misb-0.0`
How To Run
Usage:
./misb-changing-metadata-standalone [iterations] [interval_ms]
- iterations: loop count. Default is 20. Use 0 for continuous mode.
- interval_ms: delay between iterations in milliseconds. Default is 500.
Examples:
# Run 3 iterations, 50 ms interval ./misb-changing-metadata-standalone 3 50 Run forever (Ctrl+C to stop) ./misb-changing-metadata-standalone 0 200
Expected Output
You should see:
- A startup line indicating finite or continuous mode.
- Per iteration:
- INFO Formatted data generated
- Iteration N -> encoded bytes: ...
- Decoded metadata: {...} with changing tags (2, 3, 4, 5).
- For finite mode, a final Finished metadata update loop. line. Representative output:
Running 3 iterations. Metadata changes every loop. INFO Formatted data generated Iteration 0 -> encoded bytes: 86 Decoded metadata: {"key":"060E2B34020B01010E01030101000000","items":[{"tag":"2","value":"Mar. 17, 2026. 14:33:04.095"},{"tag":"3","value":"MISSION-100"},{"tag":"4","value":"AF-100"},{"tag":"5","value":"0"}, ... ]}
INFO Formatted data generated
Iteration 1 -> encoded bytes: 86
Decoded metadata: {"key":"060E2B34020B01010E01030101000000","items":[{"tag":"2","value":"Mar. 17, 2026. 14:33:04.154"},{"tag":"3","value":"MISSION-101"},{"tag":"4","value":"AF-101"},{"tag":"5","value":"10.9974823"}, ... ]}
INFO Formatted data generated
Iteration 2 -> encoded bytes: 86
Decoded metadata: {"key":"060E2B34020B01010E01030101000000","items":[{"tag":"2","value":"Mar. 17, 2026. 14:33:04.211"},{"tag":"3","value":"MISSION-102"},{"tag":"4","value":"AF-102"},{"tag":"5","value":"22.0004578"}, ... ]}
Finished metadata update loop.
Notes
The exact timestamp and numeric values vary each run. You may also see additional decoded tags (for example tag 65) inserted by codec/standard logic; this is expected.
</noinclude