OTA Connect Developer Guide

Update a secondary ECU

This page shows an example of how to use libaktualizr API to update a secondary ECU.

boost::filesystem::path cfg_path("/var/sota/sota_local.toml");
Aktualizr aktualizr(cfg_path);

This will create a new aktualizr instance based on the provided config file. Next, configure a secondary and add it to aktualizr:

Uptane::SecondaryConfig sconfig;
sconfig.secondary_type = Uptane::SecondaryType::kVirtual;
sconfig.ecu_serial = "9b6abd606a761074df0092606465ddc9";
sconfig.ecu_hardware_id = "TCU";
sconfig.full_client_dir = "/var/sota/ecus/tcu";
sconfig.ecu_private_key = "sec.private";
sconfig.ecu_public_key = "sec.public";
sconfig.target_name_path = "target_name";
sconfig.metadata_path = "/var/sota/ecus/tcu/metadata";
auto secondary = std::make_shared<Uptane::VirtualSecondary>(sconfig);

Initialize call will provision the device on the backend:


Then provide the device information (like list of ECUs, installed software versions, etc.) to the backend.


Now it is possible to query the server about currently running campaigns for the device:

auto result = aktualizr.CampaignCheck().get();
if (result.campaigns.empty()) {
  std::cout << "System is up to date" <<std::endl;

If there are some running campaigns, a vehicle owner must first give his consent for the campaign, and this consent should be communicated to the server:


Next you can get a list of available updates in the campaign:

auto update_result = aktualizr.CheckUpdates().get();

And start the download:


If you want to receive information about the download progress, you should first register an event handler:

std::function<void(const std::shared_ptr<event::BaseEvent>)> handler = event_handler;

The event_handler() function may look like this:

void event_handler(const std::shared_ptr<event::BaseEvent> &event)
  if (event->variant == "DownloadProgressReport") {
    const auto download_progress =
        dynamic_cast<event::DownloadProgressReport *>(event.get());
    std::cout << "Download progress for file "
              << download_progress->target.filename() << ": "
              << download_progress->progress << "%\n";

After the targets were downloaded, it is possible to install them, if the secondary type is supported:


Alternatively, you can get a file handle to the downloaded target and perform the installation yourself.

for (auto& target : update_result.updates) {
  std::cout << "Installing file " << target.filename();
  auto handle = aktualizr.GetStoredTarget(target);