分享一個(gè)OTA升級(jí)相關(guān)的應(yīng)用實(shí)踐!(2)
各升級(jí)情況的統(tǒng)一處理如:
左右滑動(dòng)查看全部代碼>>>
static ota_update_case_e s_ota_update_case = UPDATE_SELECTED_NULL; // 升級(jí)情況4、安裝進(jìn)度只有一個(gè),如何處理三塊板子的安裝進(jìn)度?
static ota_update_case_e s_not_yet_update_case = UPDATE_SELECTED_NULL; // 還未升級(jí)的情況
// 啟動(dòng)固件安裝
void start_firmware_install(void)
{
app_install_result_t install_board2_result = {0};
app_install_result_t install_board3_result = {0};
memset(&s_install_info, 0, sizeof(app_install_info_t));
send_install_info_to_app(&s_install_info);
memset(&install_board2_result, 0, sizeof(app_install_result_t));
memset(&install_board3_result, 0, sizeof(app_install_result_t));
send_board2_install_result_to_app(&install_board2_result);
send_board3_install_result_to_app(&install_board3_result);
s_ota_update_case = get_ota_update_case();
s_install_info.install_case = s_ota_update_case;
switch (s_ota_update_case)
{
// 固件包相同,不升級(jí)
case UPDATE_NON_DEV:
{
LOG_D("UPDATE_INSTALL_SUCCESS --- UPDATE_NON_DEV");
s_install_info.total_install_status = UPDATE_INSTALL_SUCCESS;
send_install_info_to_app(&s_install_info);
storage_write_file(APP_OTA_INSTALL_RESULT_FILE, &s_install_info.total_install_status, sizeof(install_status_e));
break;
}
// 只升級(jí)board1設(shè)備
case UPDATE_BOARD1_DEV:
{
LOG_D("UPDATE_BOARD1_DEV");
// 保存新的md5值
md5sum_t calc_board1_img_md5 = {0};
read_ota_md5_list_from_file(&s_flash_ota_file_md5_list, sizeof(s_flash_ota_file_md5_list));
calc_file_md5(OTA_BOARD1_DEV_IMG_FILE, &calc_board1_img_md5);
memcpy(s_flash_ota_file_md5_list[OTA_IMG_INDEX_BOARD1_DEV].md5, &calc_board1_img_md5, sizeof(md5sum_t));
write_ota_md5_list_to_file(&s_flash_ota_file_md5_list, sizeof(s_flash_ota_file_md5_list));
start_board1_ota_install();
break;
}
// 只升級(jí)board2設(shè)備
case UPDATE_BOARD2_DEV:
{
LOG_D("UPDATE_BOARD2_DEV");
start_board2_ota_install();
s_not_yet_update_case = UPDATE_BOARD2_DEV;
break;
}
// 只升級(jí)board3設(shè)備
case UPDATE_BOARD3_DEV:
{
LOG_D("UPDATE_BOARD3_DEV");
start_board3_ota_install();
s_not_yet_update_case = UPDATE_BOARD3_DEV;
break;
}
// 升級(jí)board1與board2設(shè)備
case UPDATE_BOARD1_AND_BOARD2_DEV:
{
LOG_D("UPDATE_BOARD1_AND_BOARD2_DEV");
start_board2_ota_install();
s_not_yet_update_case = UPDATE_BOARD1_AND_BOARD2_DEV;
break;
}
// 升級(jí)board1與board3設(shè)備
case UPDATE_BOARD1_AND_BOARD3_DEV:
{
LOG_D("UPDATE_BOARD1_AND_BOARD3_DEV");
start_board3_ota_install();
s_not_yet_update_case = UPDATE_BOARD1_AND_BOARD3_DEV;
break;
}
// 升級(jí)board2設(shè)備與board3設(shè)備
case UPDATE_BOARD2_AND_BOARD3_DEV:
{
LOG_D("UPDATE_BOARD2_AND_BOARD3_DEV");
start_board2_ota_install();
start_board3_ota_install();
s_not_yet_update_case = UPDATE_BOARD2_AND_BOARD3_DEV;
break;
}
// 升級(jí)所有設(shè)備
case UPDATE_ALL_DEV:
{
LOG_D("UPDATE_ALL_DEV");
start_board2_ota_install();
start_board3_ota_install();
s_not_yet_update_case = UPDATE_ALL_DEV;
break;
}
default:
break;
}
}
手機(jī)APP上并不會(huì)去區(qū)分各個(gè)板子的安裝進(jìn)度,即安裝進(jìn)度只有一個(gè)。因?yàn)橛脩舨⒉粫?huì)關(guān)注設(shè)備里有幾塊板子的固件在安裝。所以這個(gè)安裝進(jìn)度需要表明以上各種情況的安裝。
需要明確的是:
安裝進(jìn)度總是以board2、board3中的較大固件為主。
安裝某個(gè)板子異常則表明這個(gè)安裝過程算是失敗。為了防止這類情況:假如需要升級(jí)board1與board2,正好本次更新是增加了之間的一些協(xié)議數(shù)據(jù),如果單單升級(jí)成功其中一塊,另一塊沒升級(jí)成功,這種情況下也要去使用的話,就有可能會(huì)出現(xiàn)問題,協(xié)議數(shù)據(jù)對(duì)不上,輕則某些數(shù)據(jù)錯(cuò)誤,程序中防錯(cuò)機(jī)制設(shè)計(jì)得不好的話重則可能程序會(huì)崩潰。
雖然board2與board3的安裝進(jìn)度不直接顯示在手機(jī)APP上,但無論是給手機(jī)APP做邏輯使用還是供我們調(diào)試實(shí)用,都有必要?jiǎng)?chuàng)建他們各自的屬性數(shù)據(jù)。比如會(huì)往云端上報(bào)各種情況的board2與board3的安裝信息屬性數(shù)據(jù),如:
typedef struct app_install_result5、安裝結(jié)束的檢測(cè)?
{
uint8_t install_status; // 安裝狀態(tài)
uint8_t install_progress; // 安裝進(jìn)度
}app_install_result_t;
app_install_result_t install_board2_result = {0};
app_install_result_t install_board3_result = {0};
send_board2_install_result_to_app(&install_board2_result);
send_board3_install_result_to_app(&install_board3_result);
安裝過程包含如下幾種情況,挨個(gè)進(jìn)行處理即可:
對(duì)應(yīng)代碼如(注:以下為了方便說明全都寫在一塊,實(shí)際中可以進(jìn)行拆分):
// 檢測(cè)是否升級(jí)結(jié)束
void check_whether_update_end(void)
{
app_install_result_t install_board2_result = {0};
app_install_result_t install_board3_result = {0};
// 包含board1的升級(jí)情況(board1+board2、board1+board3、board1+board2+board3)。board1最后安裝
if (UPDATE_BOARD1_AND_BOARD2_DEV == s_ota_update_case ||
UPDATE_BOARD1_AND_BOARD3_DEV == s_ota_update_case ||
UPDATE_ALL_DEV == s_ota_update_case)
{
// 正常安裝且剩下board1沒安裝了,開始安裝board1
if (UPDATE_BOARD1_DEV == s_not_yet_update_case)
{
s_ota_update_case = UPDATE_SELECTED_NULL;
s_not_yet_update_case = UPDATE_SELECTED_NULL;
// 1. 記錄新的版本號(hào)
// 2. 保存新的md5值至本地文件
// 3.重啟之前上報(bào)安裝成功給手機(jī)APP
// 4.重啟進(jìn)行安裝board1
}
// 升級(jí)安裝失敗
else
{
// 只升級(jí)board1與board2的情況
if (UPDATE_BOARD1_AND_BOARD2_DEV == s_ota_update_case && UPDATE_BOARD1_AND_BOARD2_DEV == s_not_yet_update_case)
{
if (UPDATE_STATUS_BOARD2_DATA_ACK_ERR == s_board2_update_status)
{
s_ota_update_case = UPDATE_SELECTED_NULL;
s_not_yet_update_case = UPDATE_SELECTED_NULL;
// 1. 上報(bào)board2安裝失敗
// 2. board2安裝失敗 -> 上報(bào)總的安裝失敗
}
}
// 只升級(jí)board1與board3的情況
else if (UPDATE_BOARD1_AND_BOARD3_DEV == s_ota_update_case && UPDATE_BOARD1_AND_BOARD3_DEV == s_not_yet_update_case)
{
if (UPDATE_STATUS_BOARD3_DATA_ACK_ERR == s_board3_update_status)
{
s_ota_update_case = UPDATE_SELECTED_NULL;
s_not_yet_update_case = UPDATE_SELECTED_NULL;
// 1. 上報(bào)board3安裝失敗
// 2. board3安裝失敗 -> 上報(bào)總的安裝失敗
}
}
// 升級(jí)全部設(shè)備
else
{
// board2安裝失敗,board3安裝成功
if (UPDATE_STATUS_BOARD2_DATA_ACK_ERR == s_board2_update_status &&
UPDATE_STATUS_BOARD3_DATA_FINISH_ACK_OK == s_board3_update_status)
{
s_ota_update_case = UPDATE_SELECTED_NULL;
s_not_yet_update_case = UPDATE_SELECTED_NULL;
// 1. 上報(bào)board2安裝失敗
// 2. 上報(bào)board3安裝成功
// 3. board2安裝失敗 -> 上報(bào)總的安裝失敗
}
// board2安裝成功,board3安裝失敗
if (UPDATE_STATUS_BOARD2_DATA_FINISH_ACK_OK == s_board2_update_status && UPDATE_STATUS_BOARD3_DATA_ACK_ERR == s_board3_update_status)
{
s_ota_update_case = UPDATE_SELECTED_NULL;
s_not_yet_update_case = UPDATE_SELECTED_NULL;
// 1. 上報(bào)board2安裝成功
// 2. 上報(bào)board3安裝失敗
// 3. board3安裝失敗 -> 上報(bào)總的安裝失敗
}
// board2與board3都安裝失敗
if (UPDATE_STATUS_BOARD2_DATA_ACK_ERR == s_board2_update_status && UPDATE_STATUS_BOARD3_DATA_ACK_ERR == s_board3_update_status)
{
s_ota_update_case = UPDATE_SELECTED_NULL;
s_not_yet_update_case = UPDATE_SELECTED_NULL;
// 1. 上報(bào)board2安裝失敗
// 2. 上報(bào)board3安裝失敗
// 3. board2、board3安裝失敗 -> 上報(bào)總的安裝失敗
}
}
}
}
// 只升級(jí)board2及board3的情況。如果數(shù)據(jù)都已經(jīng)傳輸數(shù)據(jù)完成,則上報(bào)安裝完成
if (UPDATE_BOARD2_AND_BOARD3_DEV == s_ota_update_case)
{
// 升級(jí)安裝成功
if (UPDATE_NON_DEV == s_not_yet_update_case)
{
s_ota_update_case = UPDATE_SELECTED_NULL;
s_not_yet_update_case = UPDATE_SELECTED_NULL;
// 1. 上報(bào)board2安裝成功
// 2. 上報(bào)board3安裝成功
// 3. board2、board3安裝成功 -> 上報(bào)總的安裝成功
}
// 升級(jí)安裝失敗
else
{
// board2安裝失敗,board3安裝成功
if (UPDATE_STATUS_BOARD2_DATA_ACK_ERR == s_board2_update_status && UPDATE_STATUS_BOARD3_DATA_FINISH_ACK_OK == s_board3_update_status)
{
s_ota_update_case = UPDATE_SELECTED_NULL;
s_not_yet_update_case = UPDATE_SELECTED_NULL;
// 1. 上報(bào)board2安裝失敗
// 2. 上報(bào)board3安裝成功
// 3. board2安裝失敗 -> 上報(bào)總的安裝失敗
}
// board2安裝成功,board3安裝失敗
if (UPDATE_STATUS_BOARD2_DATA_FINISH_ACK_OK == s_board2_update_status && UPDATE_STATUS_BOARD3_DATA_ACK_ERR == s_board3_update_status)
{
s_ota_update_case = UPDATE_SELECTED_NULL;
s_not_yet_update_case = UPDATE_SELECTED_NULL;
// 1. 上報(bào)board2安裝成功
// 2. 上報(bào)board3安裝失敗
// 3. board3安裝失敗 -> 上報(bào)總的安裝失敗
}
// board2與board3都安裝失敗
if (UPDATE_STATUS_BOARD2_DATA_ACK_ERR == s_board2_update_status && UPDATE_STATUS_BOARD3_DATA_ACK_ERR == s_board3_update_status)
{
s_ota_update_case = UPDATE_SELECTED_NULL;
s_not_yet_update_case = UPDATE_SELECTED_NULL;
// 1. 上報(bào)board2安裝失敗
// 2. 上報(bào)board3安裝失敗
// 3. board2、board3安裝失敗 -> 上報(bào)總的安裝失敗
}
}
}
// 只升級(jí)board2的情況
if (UPDATE_BOARD2_DEV == s_ota_update_case)
{
if (UPDATE_NON_DEV == s_not_yet_update_case)
{
s_ota_update_case = UPDATE_SELECTED_NULL;
s_not_yet_update_case = UPDATE_SELECTED_NULL;
// 1. 上報(bào)board2安裝成功
// 2. board2安裝成功 -> 上報(bào)總的安裝成功
}
else
{
if (UPDATE_STATUS_BOARD2_DATA_ACK_ERR == s_board2_update_status)
{
s_ota_update_case = UPDATE_SELECTED_NULL;
s_not_yet_update_case = UPDATE_SELECTED_NULL;
// 1. 上報(bào)board2安裝失敗
// 2. board2安裝失敗 -> 上報(bào)總的安裝失敗
}
}
}
// 只升級(jí)board3的情況
if (UPDATE_BOARD3_DEV == s_ota_update_case)
{
if (UPDATE_NON_DEV == s_not_yet_update_case)
{
s_ota_update_case = UPDATE_SELECTED_NULL;
s_not_yet_update_case = UPDATE_SELECTED_NULL;
// 1. 上報(bào)board3安裝成功
// 2. board3安裝成功 -> 上報(bào)總的安裝成功
}
else
{
if (UPDATE_STATUS_BOARD3_DATA_ACK_ERR == s_board3_update_status)
{
s_ota_update_case = UPDATE_SELECTED_NULL;
s_not_yet_update_case = UPDATE_SELECTED_NULL;
// 1. 上報(bào)board3安裝失敗
// 2. board3安裝失敗 -> 上報(bào)總的安裝失敗
}
}
}
}
前面我們的升級(jí)情況進(jìn)行加法的組合,比如:
升級(jí)所有設(shè)備 = BOARD1 + BOARD2 + BOARD3 = 1 + 2 + 4
那么,我們每安裝完一個(gè)設(shè)備,可以減掉對(duì)應(yīng)的值,這樣可以區(qū)分當(dāng)前的安裝處于哪個(gè)階段。
以上就是本次的分享,大家還有什么其它思路嗎?
*博客內(nèi)容為網(wǎng)友個(gè)人發(fā)布,僅代表博主個(gè)人觀點(diǎn),如有侵權(quán)請(qǐng)聯(lián)系工作人員刪除。