Files
Eric F d398a6ced2 Add extracted tools: CitrineOS, OpenOCPP, ShapeShifter
- CitrineOS core extracted (CSMS OCPP 2.0.1)
- OpenOCPP extracted (firmware OCPP 1.6J/2.0.1)
- ShapeShifter library installed (pip install -e)
- ShapeShifter specification extracted
- EVerest extracted

TODO updated with progress
2026-06-08 00:38:27 -04:00

166 lines
8.0 KiB
C++

// SPDX-License-Identifier: Apache-2.0
// Copyright 2020 - 2025 Pionix GmbH and Contributors to EVerest
#include "rauc_dbus.hpp"
#include <everest/logging.hpp>
namespace module {
using namespace everest::lib::system;
void Rauc::configure_handlers() {
namespace interface = rauc_dbus::interface;
namespace property = rauc_dbus::property;
namespace signal = rauc_dbus::signal;
// Subscribe to Complete signal (when install_bundle command finishes)
dbus::registerSignalHandler(proxy, interface::Installer, signal::Completed, [this](sdbus::Signal signal) {
// Complete signal has one int argument
int i;
signal >> i;
if (update_request_id != request_id_default) {
if (i == 0) {
EVLOG_info << "RAUC: Installation successful, needs reboot to activate";
// Signal to the module code to store the transaction in the database.
// We will use this on next boot to signal a Success/Failed Installation
signal_store_update_transaction(create_transaction(update_request_id, timeout_us));
// The module code should reboot now since we signal InstallRebooting.
signal_firmware_update_status(types::system::FirmwareUpdateStatusEnum::InstallRebooting,
update_request_id);
} else {
EVLOG_error << "RAUC: Installation failed with error code: " << i;
if (is_installing) {
signal_firmware_update_status(types::system::FirmwareUpdateStatusEnum::InstallVerificationFailed,
update_request_id);
is_installing = false;
}
}
} else {
EVLOG_debug << "RAUC: status from another source";
}
// this was the last message, so reset request_id
update_request_id = request_id_default;
});
// Subscribe to property changes std::function<void(Signal signal)>;
dbus::registerSignalHandler(
proxy, interface::DBus_Properties, signal::PropertiesChanged, [this](sdbus::Signal signal) {
// org.freedesktop.DBus.Properties.PropertiesChanged (STRING interface_name,
// ARRAY of DICT_ENTRY<STRING,VARIANT>
// changed_properties, ARRAY<STRING>
// invalidated_properties);
std::string interface;
signal >> interface;
// ignore updates when initiated by someone else
if (update_request_id != request_id_default) {
if (interface == interface::Installer) {
std::map<std::string, sdbus::Variant> changed_properties;
signal >> changed_properties;
for (const auto& [key, value] : changed_properties) {
if (key == property::Progress) {
Progress r = value.get<Progress>();
EVLOG_info << "Progress " << r.percent << "% " << r.description;
// Map progress to OCPP structs
if (r.description.find("Verifying signature done") != std::string::npos) {
signal_firmware_update_status(types::system::FirmwareUpdateStatusEnum::Downloaded,
update_request_id);
signal_firmware_update_status(
types::system::FirmwareUpdateStatusEnum::SignatureVerified, update_request_id);
signature_verified = true;
} else if (r.description.find("Verifying signature failed") != std::string::npos) {
signal_firmware_update_status(types::system::FirmwareUpdateStatusEnum::Downloaded,
update_request_id);
signal_firmware_update_status(types::system::FirmwareUpdateStatusEnum::InvalidSignature,
update_request_id);
signature_verified = true;
// If bundle checking failed but we never got to signature verification download must
// have failed
} else if (!signature_verified &&
r.description.find("Checking bundle failed") != std::string::npos) {
signal_firmware_update_status(types::system::FirmwareUpdateStatusEnum::DownloadFailed,
update_request_id);
} else if (r.description.find("Copying") != std::string::npos &&
r.description.find("done") == std::string::npos) {
is_installing = true;
signal_firmware_update_status(types::system::FirmwareUpdateStatusEnum::Installing,
update_request_id);
}
} else if (key == property::Operation) {
auto r = rauc_dbus::rauc_messages::string_to_operation(value.get<std::string>());
if (r == Operation::Idle) {
EVLOG_info << "RAUC operation: Idle";
} else if (r == Operation::Installing) {
EVLOG_info << "RAUC operation: Installing";
}
}
}
std::vector<std::string> invalidated_properties;
signal >> invalidated_properties;
}
}
});
}
bool Rauc::decide_if_good(const rauc_dbus::rauc_messages::UpdateTransaction& saved, const CurrentState& current) {
// The original approach uses the primary slot, however this might not be
// as reliable as hoped. A change in boot slot should be more reliable
// however prior to this change the boot slot wasn't saved
bool result{false};
if (RaucBase::decide_if_good(saved, current)) {
if (saved.boot_slot.empty()) {
// use the previous approach
EVLOG_warning << "OTA: fallback to using primary slot";
result = saved.primary_slot == current.primary_slot;
} else {
// use the new approach
result = saved.boot_slot != current.boot_slot;
}
}
return result;
}
// Call on boot and pass a previous transaction that was not closed yet
void Rauc::check_previous_transaction(UpdateTransaction t) {
signal_remove_update_transaction();
if (rauc_dbus::RaucBaseSync::check_previous_transaction(t, timeout_us)) {
signal_firmware_update_status(types::system::FirmwareUpdateStatusEnum::Installed, t.request_id);
} else {
signal_firmware_update_status(types::system::FirmwareUpdateStatusEnum::InstallationFailed, t.request_id);
}
}
// Returns immediately. Progress is signalled with signal_firmware_update_status
rauc_dbus::rauc_messages::CmdResult Rauc::install_bundle(const std::string& filename, int32_t request_id) {
signature_verified = false;
is_installing = false;
update_request_id = request_id;
const auto ret = rauc_dbus::RaucBaseSync::install_bundle(filename, timeout_us);
if (ret.success) {
signal_firmware_update_status(types::system::FirmwareUpdateStatusEnum::Downloading, update_request_id);
} else {
update_request_id = request_id_default;
}
return ret;
}
bool Rauc::is_idle() {
// Note it is important to query rauc here as well as it may be busy with a local install
return (get_operation() == rauc_dbus::rauc_messages::Operation::Idle) && !is_installing;
}
} // namespace module