博客專欄

        EEPW首頁 > 博客 > 分享一個OTA升級相關(guān)的應(yīng)用實踐!(2)

        分享一個OTA升級相關(guān)的應(yīng)用實踐!(2)

        發(fā)布人:魚鷹談單片機(jī) 時間:2023-04-23 來源:工程師 發(fā)布文章

        各升級情況的統(tǒng)一處理如:

        左右滑動查看全部代碼>>>

        static ota_update_case_e s_ota_update_case = UPDATE_SELECTED_NULL;        // 升級情況
        static ota_update_case_e s_not_yet_update_case = UPDATE_SELECTED_NULL;    // 還未升級的情況

        // 啟動固件安裝
        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, 0sizeof(app_install_info_t));
            send_install_info_to_app(&s_install_info);
            memset(&install_board2_result, 0sizeof(app_install_result_t));
            memset(&install_board3_result, 0sizeof(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)
            {
                // 固件包相同,不升級
                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;
                }
                // 只升級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;
                }
                // 只升級board2設(shè)備
                case UPDATE_BOARD2_DEV:
                {
                    LOG_D("UPDATE_BOARD2_DEV");
                    start_board2_ota_install();
                    s_not_yet_update_case = UPDATE_BOARD2_DEV;
                    break;
                }
                // 只升級board3設(shè)備
                case UPDATE_BOARD3_DEV:
                {
                    LOG_D("UPDATE_BOARD3_DEV");
                    start_board3_ota_install();
                    s_not_yet_update_case = UPDATE_BOARD3_DEV;
                    break;
                }
                // 升級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;
                }
                // 升級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;
                }
                // 升級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;
                }
                // 升級所有設(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;
            }
        }
        4、安裝進(jìn)度只有一個,如何處理三塊板子的安裝進(jìn)度?

        手機(jī)APP上并不會去區(qū)分各個板子的安裝進(jìn)度,即安裝進(jìn)度只有一個。因為用戶并不會關(guān)注設(shè)備里有幾塊板子的固件在安裝。所以這個安裝進(jìn)度需要表明以上各種情況的安裝。

        需要明確的是:

        • 安裝進(jìn)度總是以board2、board3中的較大固件為主。

        • 安裝某個板子異常則表明這個安裝過程算是失敗。為了防止這類情況:假如需要升級board1與board2,正好本次更新是增加了之間的一些協(xié)議數(shù)據(jù),如果單單升級成功其中一塊,另一塊沒升級成功,這種情況下也要去使用的話,就有可能會出現(xiàn)問題,協(xié)議數(shù)據(jù)對不上,輕則某些數(shù)據(jù)錯誤,程序中防錯機(jī)制設(shè)計得不好的話重則可能程序會崩潰。

        • 雖然board2與board3的安裝進(jìn)度不直接顯示在手機(jī)APP上,但無論是給手機(jī)APP做邏輯使用還是供我們調(diào)試實用,都有必要創(chuàng)建他們各自的屬性數(shù)據(jù)。比如會往云端上報各種情況的board2與board3的安裝信息屬性數(shù)據(jù),如:

        typedef struct app_install_result
        {

            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);
        5、安裝結(jié)束的檢測?

        安裝過程包含如下幾種情況,挨個進(jìn)行處理即可:

        圖片

        對應(yīng)代碼如(注:以下為了方便說明全都寫在一塊,實際中可以進(jìn)行拆分):

        // 檢測是否升級結(jié)束
        void check_whether_update_end(void)
        {
            app_install_result_t install_board2_result = {0};
            app_install_result_t install_board3_result = {0};

            // 包含board1的升級情況(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. 記錄新的版本號
                    // 2. 保存新的md5值至本地文件
                    // 3.重啟之前上報安裝成功給手機(jī)APP
                    // 4.重啟進(jìn)行安裝board1
                }
                // 升級安裝失敗
                else
                {
                    // 只升級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. 上報board2安裝失敗
                            // 2. board2安裝失敗 -> 上報總的安裝失敗
                        }
                    }
                    // 只升級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. 上報board3安裝失敗
                            // 2. board3安裝失敗 -> 上報總的安裝失敗
                        }
                    }
                    // 升級全部設(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. 上報board2安裝失敗
                            // 2. 上報board3安裝成功
                            // 3. board2安裝失敗 -> 上報總的安裝失敗
                        }

                        // 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. 上報board2安裝成功
                            // 2. 上報board3安裝失敗
                            // 3. board3安裝失敗 -> 上報總的安裝失敗
                        }

                        // 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. 上報board2安裝失敗
                            // 2. 上報board3安裝失敗
                            // 3. board2、board3安裝失敗 -> 上報總的安裝失敗
                        }
                    }
                }
            }
            
            // 只升級board2及board3的情況。如果數(shù)據(jù)都已經(jīng)傳輸數(shù)據(jù)完成,則上報安裝完成
            if (UPDATE_BOARD2_AND_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. 上報board2安裝成功
                    // 2. 上報board3安裝成功
                    // 3. board2、board3安裝成功 -> 上報總的安裝成功
                }
                // 升級安裝失敗
                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. 上報board2安裝失敗
                        // 2. 上報board3安裝成功
                        // 3. board2安裝失敗 -> 上報總的安裝失敗
                    }

                    // 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. 上報board2安裝成功
                        // 2. 上報board3安裝失敗
                        // 3. board3安裝失敗 -> 上報總的安裝失敗
                    }

                    // 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. 上報board2安裝失敗
                        // 2. 上報board3安裝失敗
                        // 3. board2、board3安裝失敗 -> 上報總的安裝失敗
                    }
                }
            }

            // 只升級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. 上報board2安裝成功
                    // 2. board2安裝成功 -> 上報總的安裝成功
                }
                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. 上報board2安裝失敗
                        // 2. board2安裝失敗 -> 上報總的安裝失敗
                    }
                }
            }

            // 只升級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. 上報board3安裝成功
                    // 2. board3安裝成功 -> 上報總的安裝成功
                }
                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. 上報board3安裝失敗
                        // 2. board3安裝失敗 -> 上報總的安裝失敗
                    }
                }
            } 
        }

        前面我們的升級情況進(jìn)行加法的組合,比如:

        升級所有設(shè)備 = BOARD1 + BOARD2 + BOARD3 = 1 + 2 + 4

        那么,我們每安裝完一個設(shè)備,可以減掉對應(yīng)的值,這樣可以區(qū)分當(dāng)前的安裝處于哪個階段。

        以上就是本次的分享,大家還有什么其它思路嗎?


        *博客內(nèi)容為網(wǎng)友個人發(fā)布,僅代表博主個人觀點,如有侵權(quán)請聯(lián)系工作人員刪除。



        關(guān)鍵詞: AI

        相關(guān)推薦

        技術(shù)專區(qū)

        關(guān)閉
        主站蜘蛛池模板: 麻栗坡县| 会宁县| 孟州市| 手游| 镇原县| 马鞍山市| 新乡县| 丹寨县| 宁夏| 深泽县| 池州市| 花垣县| 宜宾县| 广饶县| 峡江县| 福清市| 武川县| 南涧| 武隆县| 凤凰县| 土默特右旗| 关岭| 汉阴县| 上虞市| 教育| 邹城市| 赤峰市| 中山市| 仁化县| 涿州市| 会理县| 连山| 永修县| 洪江市| 富蕴县| 南昌市| 黑水县| 弥渡县| 邻水| 盐边县| 扶绥县|