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);
aktualizr.AddSecondary(secondary);

Initialize call will provision the device on the backend:

aktualizr.Initialize();

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

aktualizr.SendDeviceData().get();

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:

aktualizr.CampaignAccept(result.campaigns[0].id).get();

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

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

And start the download:

aktualizr.Download(update_result.updates).get();

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;
aktualizr.SetSignalHandler(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:

aktualizr.Install(update_result.updates).get();

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);
  custom_install(handle);
}