mgmt: hawkbit: seperate autohandler

seperate the autohandler from the main
hawkbit source. This way the autohandler can
be disabled if it is not needed.

Signed-off-by: Fin Maaß <f.maass@vogl-electronic.com>
This commit is contained in:
Fin Maaß 2024-05-21 17:11:00 +02:00 committed by Fabio Baltieri
parent 621cf5baec
commit dce3d2de66
5 changed files with 198 additions and 171 deletions

View file

@ -88,62 +88,6 @@ int hawkbit_set_custom_data_cb(hawkbit_config_device_data_cb_handler_t cb);
*/
int hawkbit_init(void);
/**
* @brief Runs hawkBit probe and hawkBit update automatically
*
* @details The hawkbit_autohandler handles the whole process
* in pre-determined time intervals.
*
* @param auto_reschedule If true, the handler will reschedule itself
*/
void hawkbit_autohandler(bool auto_reschedule);
/**
* @brief Wait for the autohandler to finish.
*
* @param events Set of desired events on which to wait. Set to ::UINT32_MAX to wait for the
* autohandler to finish one run, or BIT() together with a value from
* ::hawkbit_response to wait for a specific event.
* @param timeout Waiting period for the desired set of events or one of the
* special values ::K_NO_WAIT and ::K_FOREVER.
*
* @retval HAWKBIT_OK if success.
* @retval HAWKBIT_NO_RESPONSE if matching events were not received within the specified time
* @retval HAWKBIT_NETWORKING_ERROR fail to connect to the hawkBit server.
* @retval HAWKBIT_UNCONFIRMED_IMAGE image is unconfirmed.
* @retval HAWKBIT_PERMISSION_ERROR fail to get the permission to access the hawkBit server.
* @retval HAWKBIT_METADATA_ERROR fail to parse or to encode the metadata.
* @retval HAWKBIT_DOWNLOAD_ERROR fail while downloading the update package.
* @retval HAWKBIT_UPDATE_INSTALLED if an update was installed. Reboot is required to apply it.
* @retval HAWKBIT_NO_UPDATE if no update was available.
* @retval HAWKBIT_CANCEL_UPDATE update was cancelled.
* @retval HAWKBIT_NOT_INITIALIZED if hawkBit is not initialized.
* @retval HAWKBIT_PROBE_IN_PROGRESS if probe is currently running.
*/
enum hawkbit_response hawkbit_autohandler_wait(uint32_t events, k_timeout_t timeout);
/**
* @brief Cancel the run of the hawkBit autohandler.
*
* @return a value from k_work_cancel_delayable().
*/
int hawkbit_autohandler_cancel(void);
/**
* @brief Set the delay for the next run of the autohandler.
*
* @details This function will only delay the next run of the autohandler. The delay will not
* persist after the autohandler runs.
*
* @param timeout The delay to set.
* @param if_bigger If true, the delay will be set only if the new delay is bigger than the current
* one.
*
* @retval 0 if @a if_bigger was true and the current delay was bigger than the new one.
* @retval otherwise, a value from k_work_reschedule().
*/
int hawkbit_autohandler_set_delay(k_timeout_t timeout, bool if_bigger);
/**
* @brief The hawkBit probe verify if there is some update to be performed.
*
@ -330,6 +274,70 @@ uint32_t hawkbit_get_poll_interval(void);
int hawkbit_reset_action_id(void);
/**
* @brief hawkBit autohandler.
* @defgroup hawkbit_autohandler hawkBit autohandler
* @ingroup hawkbit
* @{
*/
/**
* @brief Runs hawkBit probe and hawkBit update automatically
*
* @details The hawkbit_autohandler handles the whole process
* in pre-determined time intervals.
*
* @param auto_reschedule If true, the handler will reschedule itself
*/
void hawkbit_autohandler(bool auto_reschedule);
/**
* @brief Wait for the autohandler to finish.
*
* @param events Set of desired events on which to wait. Set to ::UINT32_MAX to wait for the
* autohandler to finish one run, or BIT() together with a value from
* ::hawkbit_response to wait for a specific event.
* @param timeout Waiting period for the desired set of events or one of the
* special values ::K_NO_WAIT and ::K_FOREVER.
*
* @retval HAWKBIT_OK if success.
* @retval HAWKBIT_NO_RESPONSE if matching events were not received within the specified time
* @retval HAWKBIT_NETWORKING_ERROR fail to connect to the hawkBit server.
* @retval HAWKBIT_UNCONFIRMED_IMAGE image is unconfirmed.
* @retval HAWKBIT_PERMISSION_ERROR fail to get the permission to access the hawkBit server.
* @retval HAWKBIT_METADATA_ERROR fail to parse or to encode the metadata.
* @retval HAWKBIT_DOWNLOAD_ERROR fail while downloading the update package.
* @retval HAWKBIT_UPDATE_INSTALLED if an update was installed. Reboot is required to apply it.
* @retval HAWKBIT_NO_UPDATE if no update was available.
* @retval HAWKBIT_CANCEL_UPDATE update was cancelled.
* @retval HAWKBIT_NOT_INITIALIZED if hawkBit is not initialized.
* @retval HAWKBIT_PROBE_IN_PROGRESS if probe is currently running.
*/
enum hawkbit_response hawkbit_autohandler_wait(uint32_t events, k_timeout_t timeout);
/**
* @brief Cancel the run of the hawkBit autohandler.
*
* @return a value from k_work_cancel_delayable().
*/
int hawkbit_autohandler_cancel(void);
/**
* @brief Set the delay for the next run of the autohandler.
*
* @details This function will only delay the next run of the autohandler. The delay will not
* persist after the autohandler runs.
*
* @param timeout The delay to set.
* @param if_bigger If true, the delay will be set only if the new delay is bigger than the current
* one.
*
* @retval 0 if @a if_bigger was true and the current delay was bigger than the new one.
* @retval otherwise, a value from k_work_reschedule().
*/
int hawkbit_autohandler_set_delay(k_timeout_t timeout, bool if_bigger);
/**
* @}
* @}
*/

View file

@ -7,6 +7,7 @@
zephyr_library()
zephyr_library_sources_ifdef(CONFIG_HAWKBIT hawkbit.c)
zephyr_library_sources_ifdef(CONFIG_HAWKBIT_AUTOHANDLER hawkbit_autohandler.c)
zephyr_library_sources_ifdef(CONFIG_HAWKBIT hawkbit_device.c)
zephyr_library_sources_ifdef(CONFIG_HAWKBIT hawkbit_firmware.c)
zephyr_library_sources_ifdef(CONFIG_HAWKBIT_SHELL shell.c)

View file

@ -15,7 +15,6 @@ menuconfig HAWKBIT
depends on DNS_RESOLVER
depends on JSON_LIBRARY
depends on BOOTLOADER_MCUBOOT
select EVENTS
select MPU_ALLOW_FLASH_WRITE
select IMG_ENABLE_IMAGE_CHECK
select IMG_ERASE_PROGRESSIVELY
@ -34,9 +33,17 @@ config HAWKBIT_POLL_INTERVAL
This time interval is zero and 43200 minutes(30 days). This will be overridden
by the value configured in the settings of the hawkBit server.
config HAWKBIT_AUTOHANDLER
bool "hawkBit autohandler"
select EVENTS
default y
help
Activate autohandler to handle the update process automatically.
config HAWKBIT_SHELL
bool "hawkBit shell utilities"
depends on SHELL
depends on HAWKBIT_AUTOHANDLER
help
Activate shell module that provides hawkBit commands.

View file

@ -145,13 +145,6 @@ int hawkbit_default_config_data_cb(const char *device_id, uint8_t *buffer,
static hawkbit_config_device_data_cb_handler_t hawkbit_config_device_data_cb_handler =
hawkbit_default_config_data_cb;
static void autohandler(struct k_work *work);
static K_WORK_DELAYABLE_DEFINE(hawkbit_work_handle, autohandler);
static K_WORK_DELAYABLE_DEFINE(hawkbit_work_handle_once, autohandler);
static K_EVENT_DEFINE(hawkbit_autohandler_event);
K_SEM_DEFINE(probe_sem, 1, 1);
static const struct json_obj_descr json_href_descr[] = {
@ -1480,110 +1473,3 @@ error:
k_sem_give(&probe_sem);
return hb_context.code_status;
}
static void autohandler(struct k_work *work)
{
k_event_clear(&hawkbit_autohandler_event, UINT32_MAX);
enum hawkbit_response response = hawkbit_probe();
k_event_set(&hawkbit_autohandler_event, BIT(response));
switch (response) {
case HAWKBIT_UNCONFIRMED_IMAGE:
LOG_ERR("Current image is not confirmed");
LOG_ERR("Rebooting to previous confirmed image");
LOG_ERR("If this image is flashed using a hardware tool");
LOG_ERR("Make sure that it is a confirmed image");
hawkbit_reboot();
break;
case HAWKBIT_NO_UPDATE:
LOG_INF("No update found");
break;
case HAWKBIT_CANCEL_UPDATE:
LOG_INF("hawkBit update cancelled from server");
break;
case HAWKBIT_OK:
LOG_INF("Image is already updated");
break;
case HAWKBIT_UPDATE_INSTALLED:
LOG_INF("Update installed");
hawkbit_reboot();
break;
case HAWKBIT_DOWNLOAD_ERROR:
LOG_INF("Update failed");
break;
case HAWKBIT_NETWORKING_ERROR:
LOG_INF("Network error");
break;
case HAWKBIT_PERMISSION_ERROR:
LOG_INF("Permission error");
break;
case HAWKBIT_METADATA_ERROR:
LOG_INF("Metadata error");
break;
case HAWKBIT_NOT_INITIALIZED:
LOG_INF("hawkBit not initialized");
break;
case HAWKBIT_PROBE_IN_PROGRESS:
LOG_INF("hawkBit is already running");
break;
default:
LOG_ERR("Invalid response: %d", response);
break;
}
if (k_work_delayable_from_work(work) == &hawkbit_work_handle) {
k_work_reschedule(&hawkbit_work_handle, K_SECONDS(poll_sleep));
}
}
enum hawkbit_response hawkbit_autohandler_wait(uint32_t events, k_timeout_t timeout)
{
uint32_t ret = k_event_wait(&hawkbit_autohandler_event, events, false, timeout);
for (int i = 1; i < HAWKBIT_PROBE_IN_PROGRESS; i++) {
if (ret & BIT(i)) {
return i;
}
}
return HAWKBIT_NO_RESPONSE;
}
int hawkbit_autohandler_cancel(void)
{
return k_work_cancel_delayable(&hawkbit_work_handle);
}
int hawkbit_autohandler_set_delay(k_timeout_t timeout, bool if_bigger)
{
if (!if_bigger || timeout.ticks > k_work_delayable_remaining_get(&hawkbit_work_handle)) {
hawkbit_autohandler_cancel();
LOG_INF("Setting new delay for next run: %02u:%02u:%02u",
(uint32_t)(timeout.ticks / CONFIG_SYS_CLOCK_TICKS_PER_SEC) / 3600,
(uint32_t)((timeout.ticks / CONFIG_SYS_CLOCK_TICKS_PER_SEC) % 3600) / 60,
(uint32_t)(timeout.ticks / CONFIG_SYS_CLOCK_TICKS_PER_SEC) % 60);
return k_work_reschedule(&hawkbit_work_handle, timeout);
}
return 0;
}
void hawkbit_autohandler(bool auto_reschedule)
{
if (auto_reschedule) {
k_work_reschedule(&hawkbit_work_handle, K_NO_WAIT);
} else {
k_work_reschedule(&hawkbit_work_handle_once, K_NO_WAIT);
}
}

View file

@ -0,0 +1,125 @@
/*
* Copyright (c) 2024 Vogl Electronic GmbH
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include <zephyr/mgmt/hawkbit.h>
LOG_MODULE_DECLARE(hawkbit);
static void autohandler(struct k_work *work);
static K_WORK_DELAYABLE_DEFINE(hawkbit_work_handle, autohandler);
static K_WORK_DELAYABLE_DEFINE(hawkbit_work_handle_once, autohandler);
static K_EVENT_DEFINE(hawkbit_autohandler_event);
static void autohandler(struct k_work *work)
{
k_event_clear(&hawkbit_autohandler_event, UINT32_MAX);
enum hawkbit_response response = hawkbit_probe();
k_event_set(&hawkbit_autohandler_event, BIT(response));
switch (response) {
case HAWKBIT_UNCONFIRMED_IMAGE:
LOG_ERR("Current image is not confirmed");
LOG_ERR("Rebooting to previous confirmed image");
LOG_ERR("If this image is flashed using a hardware tool");
LOG_ERR("Make sure that it is a confirmed image");
hawkbit_reboot();
break;
case HAWKBIT_NO_UPDATE:
LOG_INF("No update found");
break;
case HAWKBIT_CANCEL_UPDATE:
LOG_INF("hawkBit update cancelled from server");
break;
case HAWKBIT_OK:
LOG_INF("Image is already updated");
break;
case HAWKBIT_UPDATE_INSTALLED:
LOG_INF("Update installed");
hawkbit_reboot();
break;
case HAWKBIT_DOWNLOAD_ERROR:
LOG_INF("Update failed");
break;
case HAWKBIT_NETWORKING_ERROR:
LOG_INF("Network error");
break;
case HAWKBIT_PERMISSION_ERROR:
LOG_INF("Permission error");
break;
case HAWKBIT_METADATA_ERROR:
LOG_INF("Metadata error");
break;
case HAWKBIT_NOT_INITIALIZED:
LOG_INF("hawkBit not initialized");
break;
case HAWKBIT_PROBE_IN_PROGRESS:
LOG_INF("hawkBit is already running");
break;
default:
LOG_ERR("Invalid response: %d", response);
break;
}
if (k_work_delayable_from_work(work) == &hawkbit_work_handle) {
k_work_reschedule(&hawkbit_work_handle, K_SECONDS(hawkbit_get_poll_interval()));
}
}
enum hawkbit_response hawkbit_autohandler_wait(uint32_t events, k_timeout_t timeout)
{
uint32_t ret = k_event_wait(&hawkbit_autohandler_event, events, false, timeout);
for (int i = 1; i < HAWKBIT_PROBE_IN_PROGRESS; i++) {
if (ret & BIT(i)) {
return i;
}
}
return HAWKBIT_NO_RESPONSE;
}
int hawkbit_autohandler_cancel(void)
{
return k_work_cancel_delayable(&hawkbit_work_handle);
}
int hawkbit_autohandler_set_delay(k_timeout_t timeout, bool if_bigger)
{
if (!if_bigger || timeout.ticks > k_work_delayable_remaining_get(&hawkbit_work_handle)) {
hawkbit_autohandler_cancel();
LOG_INF("Setting new delay for next run: %02u:%02u:%02u",
(uint32_t)(timeout.ticks / CONFIG_SYS_CLOCK_TICKS_PER_SEC) / 3600,
(uint32_t)((timeout.ticks / CONFIG_SYS_CLOCK_TICKS_PER_SEC) % 3600) / 60,
(uint32_t)(timeout.ticks / CONFIG_SYS_CLOCK_TICKS_PER_SEC) % 60);
return k_work_reschedule(&hawkbit_work_handle, timeout);
}
return 0;
}
void hawkbit_autohandler(bool auto_reschedule)
{
if (auto_reschedule) {
k_work_reschedule(&hawkbit_work_handle, K_NO_WAIT);
} else {
k_work_reschedule(&hawkbit_work_handle_once, K_NO_WAIT);
}
}